Still learning the ins and outs of python here. I've had minor success with using openpyxl library and started this pet project of using excel file as a "canvas" to read a 1 bit bmp file from directory then to "duplicate-display" the image on the worksheet by getting rid of the guides, decreasing the sizes of each cell and finally by adding a small image in each cell with list of binary data from getdata method from pillow.
I have not gone through the entire logic, but I am having trouble with below code for two nights and I still have no clue why I am getting name 'openpyxl' not defined error in the line almost at the bottom withe the code sheet.add_image(openpyxl.drawing.image.Image('square_blue.jpg'), colnum_string(col)+str(row))
I had success with similar project using almost identical importing of both openpyxl and PIL libraries.
from openpyxl import Workbook
import os
from PIL import Image
# for file in os.listdir():
# if file.endswith('bmp'):
os.chdir('c:/users/Sam/Desktop/py')
img = Image.open('trump.bmp')
img_width, img_height = img.size
pix_val = list(img.getdata())
wb = Workbook()
def colnum_string(n):
string = ""
while n > 0:
n, remainder = divmod(n - 1, 26)
string = chr(65 + remainder) + string
return string
r_height = 3
c_width = 3
sheet = wb.create_sheet("Mysheet")
for col in range(1, img_height):
sheet.row_dimensions[img_height].height = r_height
for row in range(1, img_width):
sheet.column_dimensions[colnum_string(col)] = c_width
sheet.add_image(openpyxl.drawing.image.Image('square_blue.jpg'), colnum_string(col)+str(row))
wb.save('out.xlsx')
Can anyone help me out please?
You only import ''Workbook'' sub-module from openpyxel. Try:
from openpyxel import Workbook, drawing # also import drawing namespace
[...]
sheet.add_image(drawing.image.Image('square_blue.jpg'), colnum_string(col)+str(row))
[...]
Related
I want to make a python screenshot taker, so i tried to make it take screenshots, and i thought that i could just f.write(NewByteArray), but it didn't work, i got some errors, here:
Traceback (most recent call last):
File "C:\Users\*******\OneDrive\Área de Trabalho\Meu Computador\Programas\Python\GC YT Maker\Gacha Club Screenshot taker.py", line 22, in <module>
BiteArray = bytearray(image)
TypeError: cannot convert 'PngImageFile' object to bytearray
and i don't know what to do anymore, here's all my code btw:
import os
import sys
import pyautogui
import pyscreenshot
from PIL import Image
SCREEN_X1 = 10
SCREEN_Y1 = 10
# X1 Position of the background
# Y1 Position of the background
SCREEN_X2 = 255
SCREEN_Y2 = 255
# X2 Position of the background
# Y2 Position of the background
Filename = 0
FILENAME = f'{Filename}.png'
image = pyscreenshot.grab(bbox=(SCREEN_X1, SCREEN_Y1, SCREEN_X2, SCREEN_Y2))
#image.show()
BiteArray = bytearray(image)
with open(FILENAME, 'wb') as f:
f.write(BiteArray)
f.close
Filename += 1
the module returns a PIL image, which has the save function for this exact purpose.
image.save(FILENAME)
but if you want to manually write it to disk yourself, you can first save it in a BytesIO object then save it to desk ...
import io
BiteArray = io.BytesIO()
image.save(BiteArray,format='png')
with open(FILENAME, 'wb') as f:
f.write(BiteArray.getvalue())
f.close() # notice don't need to call this function
this is probably useful if you get paid by the number of lines in your code and 6 lines instead of 1 means more pay
jokes aside, this may be useful if you weren't writing it to disk the normal way, like sending it over network.
You can do this only using the pyautogui module.
pyautogui.screenshot(region=(0,0, 300, 400))
Reference
To start, I know very little about Python. I am trying to convert a CSV to A wav file using a script I found in another post. Best I can tell it was written for an older version of python than the one I am using. One error I am getting is because of the version difference, I am just not sure how to correct it. The other error may be because of my ignorance with Python, but I am not sure of that.
The first error is:
Python\CVS-WAV2.py:44: DeprecationWarning: 'U' mode is deprecated
for time, value in csv.reader(open(fname, 'U'), delimiter=','):
I know in Python 3 the 'U' has been replaced with newline= with either "None, '\n', '\r', or '\n\r'. After reading up on the newline function I think that "None" is the option I want.
Once I change 'U' to newlinw=None, My first error goes away but I still get the following when I run the script:
File "\Python\CVS-WAV2.py", line 43, in
for time, value in csv.reader(open(fname, newline='\n'), delimiter=','):
ValueError: not enough values to unpack (expected 2, got 0)
I am not sure how to resolve this error though.
#!/usr/bin/python
import wave
import struct
import sys
import csv
import numpy
from scipy.io import wavfile
from scipy.signal import resample
def write_wav(data, filename, framerate, amplitude):
wavfile = wave.open(filename,'w')
nchannels = 1
sampwidth = 2
framerate = framerate
nframes = len(data)
comptype = "NONE"
compname = "not compressed"
wavfile.setparams((nchannels,
sampwidth,
framerate,
nframes,
comptype,
compname))
frames = []
for s in data:
mul = int(s * amplitude)
frames.append(struct.pack('h', mul))
frames = ''.join(frames)
wavfile.writeframes(frames)
wavfile.close()
print("%s written" %(filename))
if __name__ == "__main__":
if len(sys.argv) <= 1:
print ("You must supply a filename to generate")
exit(-1)
for fname in sys.argv[1:]:
data = []
for time, value in csv.reader(open(fname, newline=None), delimiter=','):
try:
data.append(float(value))#Here you can see that the time column is skipped
except ValueError:
pass # Just skip it
arr = numpy.array(data)#Just organize all your samples into an array
# Normalize data
arr /= numpy.max(numpy.abs(data)) #Divide all your samples by the max sample value
filename_head, extension = fname.rsplit(".", 1)
data_resampled = resample( arr, len(data) )
wavfile.write('rec.wav', 2000, data_resampled) #resampling at 2khz
print ("File written succesfully !")
Any help would be greatly appreciated!!
There are probably empty lines in your CSV file. One way to skip over those is to use the following:
for record in csv.reader(open(fname, newline=None), delimiter=','):
if not record:
continue
time, value = record
I am trying to create an input pipeline using the tf.data API. I have 3D data and using normal NumPy operations I would've ended up with an array with dimensions [?,256x256x3x100], which one can think of as 100 frames each of 256x256x3 size.
import glob
import os
import numpy as np
import tensorflow.compat.v1 as tf
def readfile(filenames):
flag = 0
for name in filenames:
string = tf.read_file(name)
image = tf.image.decode_image(string, channels=3)
if flag == 0:
bunch = image
flag = 1
else:
bunch = tf.concat([bunch,image],1)
return bunch
with tf.device("/cpu:0"):
train_files = []
for s in [x[0] for x in os.walk("path/to/data/folders")]:
if(s == "path/to/data/folders"):
continue
train_files.append(glob.glob(s+"/*.png"))
# shape of train_files is [5,100]
train_dataset = tf.data.Dataset.from_tensor_slices(train_files)
train_dataset = train_dataset.map(readfile, num_parallel_calls=16)
I think the error is occurring because 'bunch' is changing size in for loop. Error:
ValueError Traceback (most recent call last)
<ipython-input-13-c2f88ca344dc> in <module>
22 train_dataset = train_dataset.map(
---> 23 readfile, num_parallel_calls=16)
ValueError: in converted code:
ValueError: TensorFlow requires that the following symbols must be defined before the loop: ('bunch',)
How do I read the data correctly?
EDIT
What worked for me:
def readfile(filenames):
flag = 0
name = filenames[0]
string = tf.read_file(name)
image = tf.image.decode_image(string, channels=3)
bunch = image
for name in filenames:
string = tf.read_file(name)
image = tf.image.decode_image(string, channels=3)
if flag == 0:
bunch = image
flag = 1
else:
bunch = tf.concat([bunch,image],1)
return bunch
So I'm not sure why it is necessary to initialise bunch before the loop, when the first iteration should take care of that bunch = image. It might be because flag is not defined as a tensor so bunch = image is never actually run?
The variable bunch is created inside the function readfile() and therefore the error, because variables cannot be created inside the loop at run time. A fix would be to move the declaration of the variable bunch outside the loop. Code sample follows:
import glob
import os
import numpy as np
import tensorflow.compat.v1 as tf
def readfile(filenames):
flag = 0
bunch = <some_appropriate_initialization>
for name in filenames:
string = tf.read_file(name)
image = tf.image.decode_image(string, channels=3)
if flag == 0:
bunch = image
flag = 1
else:
bunch = tf.concat([bunch,image],1)
return bunch
# Rest of the code
You can't use arbitrary python code inside a dataset.map function, that is readfile in your case. There are two ways to solve this:
By using readfile code as it is and by calling it astf.py_function instead, here you can do eager execution, hence you can write any python logic as normal.
By converting the code in readfile and making use of only tensorflow functions to do the transformation. Performance-wise this is much better than using tf.py_function.
You can find an example on both at https://www.tensorflow.org/api_docs/python/tf/py_function
I know there is a rawpy python library to open the raw file, but in order to modify the pixel data, the original data from raw need to be demosaiced. Could anyone provide a solution to swap the color channel for raw file encoded as BGGR? Thanks!
Edit1: I now have a python(2.7) script that can does the job but saves it as tiff format instead of raw.
import rawpy
import imageio
path = 'xxxx.raw'
raw = rawpy.imread(path)
rgb = raw.postprocess()
for x in rgb:
for y in x:
temp = y[0]
y[0] = y[2]
y[2] = temp
raw.raw_image
imageio.imsave('default.tiff', rgb)
Basically the question is how can I store the image back into raw format? Is the conversion from tiff to raw lossy?
Additionally, is there any way to not demosaic the raw file and swap the bytes(SBGGR8 to SRGGB8)? This way seems no data loss problem.
Edit2: Here is my raw metadata process MATLAB code that can swap the channel lossless. But MATLAB is not free software, I am looking for a python version. As I am not a python file process expert, could somebody help me with my script?
row = 640; col = 480;
fin = fopen('original.raw','r');
input = fread(fin,row*col,'uint8=>uint8');
output = reshape(input,row,col);
for y = 1:2:639
for x = 1:2:479
temp = output(y,x);
output(y,x) = output(y+1, x+1);
output(y+1, x+1) = temp;
end
end
fout = fopen('swapped.raw', 'w');
fwrite(fout,output);
fclose(fin);
fclose(fout);
This is the lossless way of swapping the B and R channel by using Python 2.7.
#!/usr/bin/python2.7
import numpy as np
row = 480
col = 640
fin = open('example.raw','r')
inp = np.fromfile(fin,np.dtype(np.uint8),row*col)
output = np.reshape(inp,(row,col))
def my_range(start, end, step):
while start <= end:
yield start
start += step
for y in my_range(0, row-2, 2):
for x in my_range(0, col-2, 2):
temp = output[y][x]
output[y][x] = output[y+1][x+1]
output[y+1][x+1] = temp
fout = open('output.raw','w')
fout.writelines(output)
fin.close()
fout.close()
Is there a way to read in a bmp file in Python that does not involve using PIL? PIL doesn't work with version 3, which is the one I have. I tried to use the Image object from graphics.py, Image(anchorPoint, filename), but that only seems to work with gif files.
In Python it can simply be read as:
import os
from scipy import misc
path = 'your_file_path'
image= misc.imread(os.path.join(path,'image.bmp'), flatten= 0)
## flatten=0 if image is required as it is
## flatten=1 to flatten the color layers into a single gray-scale layer
I realize that this is an old question, but I found it when solving this problem myself and I figured that this might help someone else in the future.
It's pretty easy actually to read a BMP file as binary data. Depending on how broad support and how many corner-cases you need to support of course.
Below is a simple parser that ONLY works for 1920x1080 24-bit BMP's (like ones saved from MS Paint). It should be easy to extend though. It spits out the pixel values as a python list like (255, 0, 0, 255, 0, 0, ...) for a red image as an example.
If you need more robust support there's information on how to properly read the header in answers to this question: How to read bmp file header in python?. Using that information you should be able to extend the simple parser below with any features you need.
There's also more information on the BMP file format over at wikipedia https://en.wikipedia.org/wiki/BMP_file_format if you need it.
def read_rows(path):
image_file = open(path, "rb")
# Blindly skip the BMP header.
image_file.seek(54)
# We need to read pixels in as rows to later swap the order
# since BMP stores pixels starting at the bottom left.
rows = []
row = []
pixel_index = 0
while True:
if pixel_index == 1920:
pixel_index = 0
rows.insert(0, row)
if len(row) != 1920 * 3:
raise Exception("Row length is not 1920*3 but " + str(len(row)) + " / 3.0 = " + str(len(row) / 3.0))
row = []
pixel_index += 1
r_string = image_file.read(1)
g_string = image_file.read(1)
b_string = image_file.read(1)
if len(r_string) == 0:
# This is expected to happen when we've read everything.
if len(rows) != 1080:
print "Warning!!! Read to the end of the file at the correct sub-pixel (red) but we've not read 1080 rows!"
break
if len(g_string) == 0:
print "Warning!!! Got 0 length string for green. Breaking."
break
if len(b_string) == 0:
print "Warning!!! Got 0 length string for blue. Breaking."
break
r = ord(r_string)
g = ord(g_string)
b = ord(b_string)
row.append(b)
row.append(g)
row.append(r)
image_file.close()
return rows
def repack_sub_pixels(rows):
print "Repacking pixels..."
sub_pixels = []
for row in rows:
for sub_pixel in row:
sub_pixels.append(sub_pixel)
diff = len(sub_pixels) - 1920 * 1080 * 3
print "Packed", len(sub_pixels), "sub-pixels."
if diff != 0:
print "Error! Number of sub-pixels packed does not match 1920*1080: (" + str(len(sub_pixels)) + " - 1920 * 1080 * 3 = " + str(diff) +")."
return sub_pixels
rows = read_rows("my image.bmp")
# This list is raw sub-pixel values. A red image is for example (255, 0, 0, 255, 0, 0, ...).
sub_pixels = repack_sub_pixels(rows)
Use pillow for this. After you installed it simply import it
from PIL import Image
Then you can load the BMP file
img = Image.open('path_to_file\file.bmp')
If you need the image to be a numpy array, use np.array
img = np.array(Image.open('path_to_file\file.bmp'))
The numpy array will only be 1D. Use reshape() to bring it into the right shape in case your image is RGB. For example:
np.array(Image.open('path_to_file\file.bmp')).reshape(512,512,3)
I had to work on a project where I needed to read a BMP file using python, it was quite interesting, actually the best way is to have a review on the BMP file format (https://en.wikipedia.org/wiki/BMP_file_format) then reading it as binairy file, to extract the data.
You will need to use the struct python library to perform the extraction
You can use this tutorial to see how it proceeds https://youtu.be/0Kwqdkhgbfw
Use the excellent matplotlib library
import matplotlib.pyplot as plt
im = plt.imread('image.bmp')
It depends what you are trying to achieve and on which platform?
Anyway using a C library to load BMP may work e.g. http://code.google.com/p/libbmp/ or http://freeimage.sourceforge.net/, and C libraries can be easily called from python e.g. using ctypes or wrapping it as a python module.
or you can compile this version of PIL https://github.com/sloonz/pil-py3k
If you're doing this in Windows, this site, should allow you to get PIL (and many other popular packages) up and running with most versions of Python: Unofficial Windows Binaries for Python Extension Packages
The common port of PIL to Python 3.x is called "Pillow".
Also I would suggest pygame library for simple tasks. It is a library, full of features for creating games - and reading from some common image formats is among them. Works with Python 3.x as well.