Reputation: 439
I would like to write a script that reads a bmp file and then notes the pixels on the x-y axes where the image is a color other than white. Then with this data, save it into a .txt file.
I have started using the Pillow library but haven't found how to solve this problem. I opened the bmp file with Pillow and tried to play around with the modules from Image but I couldn't find how to make this work.
Thanks in advance!
Upvotes: 3
Views: 9922
Reputation: 10860
EDIT:
Just realized, that the question was about finding the indices of all pixels which are different from white...
For this case just replace the calculation of the boolean array by its complement function:
white = (img[:, :, :3] != 255).any(2)
or
simply add a ~
in front of the boolean array in np.where
:
coords = np.array(np.where(~white))[::-1].T
test result then would be consequently the opposite
Here I assume "using PIL" is not a strict requirement, but only a sign of how you tried to start.
That said, you can do the following, using imread
from imageio
:
import numpy as np
from imageio import imread
img = imread(filename)
white = (img[:, :, :3] == 255).all(2)
coords = np.array(np.where(white))[::-1].T
writing into an ascii file could be done like
with open('xycoordinates.txt', 'w') as f:
for c in coords:
f.write(f'{c[0]},{c[1]}\n')
Explanation
img
is a 3D-array, of shape (nr, nc, c)
, i.e. number of rows, number of columns and RGBA-values.
img[:, :, :3] == 255
returns a boolean array of the same shape like img
, indicating componentwise matching of the single RGB values (without respect to A. If A should be 255, too, just leave away the complete indexing brackets).
.all(2)
reduces it to the desired array of shape (nr, nc)
by setting only those indices to True
, where the complete RGBA-array matches.
np.where(white)
returns a tuple of the row- and column-indices.
np.array()
casts it into a numpy array in order to apply numpy indexing and transformation to it.
As row/column
is the opposite order of a x/y
nomenclature, [::-1]
reverses the order of the two index arrays.
Transformation by .T
is done to output not two arrays (x
and y
) of n indices, but n arrays of (x, y)
indices.
Example
img = imread(samplefile)
plt.imshow(img)
white = (img == [255, 255, 255, 255]).all(2)
array([[False, False, True, False, False, False],
[False, False, True, True, False, False],
[False, True, False, False, False, False],
[ True, True, False, False, False, False],
[False, False, False, False, False, True]])
coords = np.array(np.where(white))[::-1].T
array([[2, 0],
[2, 1],
[3, 1],
[1, 2],
[0, 3],
[1, 3],
[5, 4]], dtype=int64)
plt.plot(*coords.T, 'ro')
Upvotes: 3
Reputation: 439
You can read pixels with Image.getpixel()
from PIL.
The code below will give you all non-white pixels in the form of a 2D list.
from PIL import Image
im = Image.open('x.bmp')
imageSizeW, imageSizeH = im.size
nonWhitePixels = []
for i in range(1, imageSizeW):
for j in range(1, imageSizeH):
pixVal = im.getpixel((i, j))
if pixVal != (255, 255, 255):
nonWhitePixels.append([i, j])
print(nonWhitePixels)
Upvotes: 5