Count number of White Pixels per row of an image in Python - python

I am stuck trying to count the number of white pixels per row in a image.
i have tried this
img = cv2.imread("11.jpg") # Its our Image object
mask = np.uint8(np.where(img == 0, 1, 0))
row_counts = cv2.reduce(mask, 1, cv2.REDUCE_SUM, dtype=cv2.CV_32SC1) # type: ignore
#Data Collection
White_row = 224- row_counts # 224 is max pixels in row

So i made my own loop algorithm that loops through every pixel and checks the pixel intensity. The image is converted into grey scale.
img = Image.open("11.jpg")
img = img.convert("L") # convert to grayscale
pix = img.load()
width, height = img.size
print(width, height)
print(pix[91,134]) #Tester
White_row = [0] * height
for y in range(height):
for x in range(width):
if pix[x,y] > 235: # 235 is the threshold
White_row[y] += 1
Max_Width = np.max(White_row)
Mean_Width = np.mean(White_row)
print ("Max_Width: ", Max_Width)
print ("Mean_Width: ", Mean_Width)

Related

How do I create a checker board pattern?

I am trying to write a code that can generate an checker board pattern. The final image size should be 100 x 100, the checker board size 5 x 5, such that each box has dimensions h/5 and w/5. The code I have is wrong:
from PIL import Image, ImageDraw
h = 500
w = 500
img = Image.new("RGB", (h,w), (255, 0, 0)) # create a new 15x15 image
pixels = img.load() # create the pixel map
print("1")
for i in range (h):
for j in range(w):
if ((i + j)%2) != 0:
im = Image.new('RGB', (h//5, w//5), 'black')
else:
draw = ImageDraw.Draw(img, "RGBA")
draw.rectangle(((h//5, w//5), (i+.5, j+.5)), fill="blue")
print ("done")
img.show()
I know it's already been answered, here's a way to loop over it differently
from PIL import Image
h = 500
w = 500
# You can also easily set the number of squares per row
number_of_square_across = 10
# You can also easily set the colors
color_one = (0, 0, 0)
color_two = (0, 0, 255)
length_of_square = h/number_of_square_across
length_of_two_squares = h/number_of_square_across*2
img = Image.new("RGB", (h, w), (255, 0, 0)) # create a new 15x15 image
pixels = img.load() # create the pixel map
for i in range(h):
# for every 100 pixels out of the total 500
# if its the first 50 pixels
if (i % length_of_two_squares) >= length_of_square:
for j in range(w):
if (j % length_of_two_squares) < length_of_square:
pixels[i,j] = color_one
else:
pixels[i,j] = color_two
# else its the second 50 pixels
else:
for j in range(w):
if (j % length_of_two_squares) >= length_of_square:
pixels[i,j] = color_one
else:
pixels[i,j] = color_two
print("done")
img.show()
For anyone who reads this in the future and is looking for a general solution to make a checker board see here:
M, N = 10, 10
arr = [[0 for _ in range(N)] for _ in range(M)] # an M by N array
for i in range(M):
for j in range(N):
if (i&1)^(j&1): # if (i is odd and j is even) or (j is odd and i is even)
arr[i][j] = 1 # change the pixel from white to black
Solution tailored specifically to the OP's inquiry see here:
from PIL import Image, ImageDraw
h = 500
w = 500
img = Image.new("RGB", (h,w), (255, 0, 0)) # create a new 15x15 image
pixels = img.load() # create the pixel map
print ("1")
for i in range (h):
for j in range(w):
if (i&1)^(j&1):
pixels[i,j] = (0, 0, 0)
else:
pixels[i,j] = (0, 0, 255)
print ("done")
img.show()
# BIGGER BOX SIZE
from PIL import Image, ImageDraw
h = 500
w = 500
img = Image.new("RGB", (h,w), (255, 0, 0)) # create a new 15x15 image
pixels = img.load() # create the pixel map
print ("1")
box_size = 25
for i in range (0, h, box_size):
for j in range(0, w, box_size):
y, x = i // box_size, j // box_size
if (y&1)^(x&1):
for di in range(box_size):
for dj in range(box_size):
pixels[i+di,j+dj] = (0, 0, 0)
else:
for di in range(box_size):
for dj in range(box_size):
pixels[i+di,j+dj] = (0, 0, 255)
print ("done")
img.show()
This will get you the checker pattern for an array.
I had the feeling, that accessing single pixels in Pillow using all those nested loops isn't the best idea performance-wise.
So, my idea would be to set up a small (m, n) checker using (nested) lists, build a Pillow Image object from that using putdata, and simply resize it to the desired size using the Image.NEAREST resampling filter. I added some flexibility for choosing colors and image modes.
from itertools import chain
from math import ceil
from PIL import Image
m, n = (5, 5) # Checker dimension (x, y)
w, h = (100, 100) # Final image width and height
c1 = 0 # (224, 64, 64) # First color
c2 = 255 # (128, 128, 128) # Second color
mode = 'L' if isinstance(c1, int) else 'RGB' # Mode from first color
# Generate pixel-wise checker, even x dimension
if m % 2 == 0:
pixels = [[c1, c2] for i in range(int(m/2))] + \
[[c2, c1] for i in range(int(m/2))]
pixels = [list(chain(*pixels)) for i in range(ceil(n/2))]
# Generate pixel-wise checker, odd x dimension
else:
pixels = [[c1, c2] for i in range(ceil(m*n/2))]
# Generate final Pillow-compatible pixel values
pixels = list(chain(*pixels))[:(m*n)]
# Generate Pillow image from pixel values, resize to final image size, and save
checker = Image.new(mode, (m, n))
checker.putdata(pixels)
checker = checker.resize((w, h), Image.NEAREST)
checker.save('checker.png')
For the shown configuration, the output would be:
Switching to RGB, and altering m, w, and h, we might get something like this:
As already pointed out in the other answers, if w or h are not whole integer factors of m or n, then you'll get somehow distorted output (m = n = 5, w = h = 102):
----------------------------------------
System information
----------------------------------------
Platform: Windows-10-10.0.16299-SP0
Python: 3.9.1
Pillow: 8.1.2
----------------------------------------

Blue Image Filter in python

I am trying to write a function that takes a pixel as a parameter and inverts each color in the pixel then return the new color values as a tuple. Help would be much appreciated Here is my current code:
IMAGE_URL = "https://codehs.com/uploads/c709d869e62686611c1ac849367b3245"
IMAGE_WIDTH = 280
IMAGE_HEIGHT = 200
image = Image(IMAGE_URL)
image.set_position(70, 70)
image.set_size(IMAGE_WIDTH, IMAGE_HEIGHT)
add(image)
#################################################
# Write your function here. Loop through each pixel
# and set each pixel to have a zero blue value.
#################################################
def remove_blue():
pass
# Give the image time to load
print("Removing Blue Channel ....")
print("Might take a minute....")
timer.set_timeout(remove_blue, 1000)
from PIL import Image
# open image
image = Image.open('pic.jpeg')
# show the image (optional)
image.show()
# load the image into memory
image_data = image.load()
# obtain sizes
height,width = image.size
# loop over and change blue value to 0
for loop1 in range(height):
for loop2 in range(width):
r,g,b = image_data[loop1,loop2]
image_data[loop1,loop2] = r,g,0
image.save('changed.jpeg')
The corresponding function would be
def remove_blue(image):
image = Image.open('pic.jpeg')
# show the image (optional)
image.show()
# load the image into memory
image_data = image.load()
# obtain sizes
height,width = image.size
# loop over and change blue value to 0
for loop1 in range(height):
for loop2 in range(width):
r,g,b = image_data[loop1,loop2]
image_data[loop1,loop2] = r,g,0
# return image
image.save('changed.jpeg')

Inserting 2d-array into another 2d-array, while taking values into account

Im trying to insert one picture(transparent .png) into another on certain coordinates.
While the solution from How to add an image over another image using x,y coordinates?
frame[y: y+insert_size[1], x: x+insert_size[0]] = image (where insert_size - width and height of inserted picture) works, i also dont want black pixels(thats how opencv represents transparent pixels) on the final image.
I wrote a function that iterates pixel by pixel, and while it works - it is horribly slow(it completes about 2 image inserts per second), code:
def insert_image(frame, image, insert_coordinates, masked_value):
img_height = len(image)
img_width = len(image[0])
mask = np.ndarray((3,), np.uint8, buffer=np.array(masked_value))
y_diff = 0 #current vertical position in insert picture
for y, line in enumerate(frame):
if y_diff == img_height-1:
continue #interested until last row
if y < insert_coordinates[1] or y > insert_coordinates[1]+img_height:
continue #interested only in rows that will be changed
else:
x_diff = 0 #current horizontal position in insert picture
for x, col in enumerate(line):
if x_diff == img_width-1:
continue #interested until last column
if x < insert_coordinates[0] or x > insert_coordinates[0]+img_width:
continue #interested only in columns that will be changed
else:
if (image[y_diff][x_diff] != mask).all():
frame[y][x] = image[y_diff][x_diff] #setting pixel value if its not of masked value
x_diff += 1
y_diff += 1
return frame
maybe there is a smarter way to do so?
opencv version 4.5.0
numpy version 1.20.0rc1
UPDATE:
By "insert" i do mean assign a pixel value from image to some pixel of frame.
i added data and code for reproducible example(also modified function so its a bit faster):
"frame" - original picture, that image will be added to to, has red square sized (500,500) at (100,100) coordinates
"image" - transparent .png, sized (500,500) that will be "inserted" into original frame
"result1" - result, where red pixels were replaced with black "transparent" pixels from inserted image
"result2" - desired result
code, requires opencv-python and numpy modules: example.py
import cv2
import numpy as np
import copy
def insert_image_v2(frame, image, insert_coordinates, masked_value):
img_height = len(image)
img_width = len(image[0])
mask = np.ndarray((3,), np.uint8, buffer=np.array(masked_value))
y_diff = 0
for y in range(insert_coordinates[1], insert_coordinates[1]+img_height, 1):
x_diff = 0
for x in range(insert_coordinates[0], insert_coordinates[0]+img_width, 1):
if (image[y_diff][x_diff] != mask).all():
frame[y][x] = image[y_diff][x_diff]
x_diff += 1
y_diff += 1
return frame
if __name__ == "__main__":
frame = cv2.imread('frame.png')
image = cv2.imread('image.png')
insert_size = (image.shape[0], image.shape[1])
insert_coordinates = (100, 100)
x = insert_coordinates[0]
y = insert_coordinates[1]
result1 = copy.deepcopy(frame)
result1[y: y+insert_size[1], x: x+insert_size[0]] = image
result2 = insert_image_v2(frame, image, insert_coordinates, [0,0,0])
cv2.imshow('result1', result1)
cv2.imshow('result2', result2)
cv2.imwrite('result1.jpg', result1)
cv2.imwrite('result2.jpg', result2)
print()
Found a solution in Image alpha composite with OpenCV, it is about 20 times faster than what i had. code:
import cv2
import numpy as np
import time
def insert_image_v2(frame, image, insert_coordinates):
x = insert_coordinates[0]
y = insert_coordinates[1]
insert_size = (image.shape[1], image.shape[0])
background = frame[y: y+insert_size[1], x: x+insert_size[0]]
foreground = image
kernel = np.ones((5,5), np.uint8)
image_gray = cv2.cvtColor(foreground, cv2.COLOR_BGR2GRAY)
ret, mask = cv2.threshold(image_gray, 1, 255, cv2.THRESH_BINARY_INV)
opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
output = np.zeros(foreground.shape, dtype=foreground.dtype)
for i in range(3):
output[:,:,i] = background[:,:,i] * (opening/255)+foreground[:,:,i]*(1-opening/255)
frame[y: y+insert_size[1], x: x+insert_size[0]] = output
return frame
if __name__ == "__main__":
frame = cv2.imread('frame.png')
image = cv2.imread('image_1.png')
insert_size = (image.shape[0], image.shape[1])
insert_coordinates = (100, 100)
t1 = time.time()
frame = insert_image_v2(frame, image, insert_coordinates)
t2 = time.time()
print(f"{t2-t1}")
cv2.imshow('img', frame)
cv2.waitKey(0)

Python Pillow Creating an Image with List of Pixels

I have a .txt file that contains coordinates and color codes. I want to create an image from this
My example txt file:
1,1#f8f3ed
1,2#fff9f1
1,3#faf2e7
1,4#fbf2e1
1,5#f6eed9
1,6#e1d6c0
1,7#e2d6be
1,8#ebdfc5
1,9#d0c4ac
1,10#cdc2ac
1,11#e3dbc6
1,12#ded7c5
.
.
187,249#1b2019
How can I create this image?
Edited code as below:
from PIL import Image
from PIL import ImageColor
path_to_file = 'data.txt'
img_data = []
height = 0
width = 0
# The first step is to read the file
with open(path_to_file) as f:
lines = f.readlines()
# Strip off new lines
lines = [x.strip('\n') for x in lines]
for line in lines:
x,y = line[:-7].split(',')
# I'm assuming from the data that the x,y vals start at 1,1. Subtract 1 from each value so they are zero indexed.
x = int(x) - 1
y = int(y) - 1
color = line[-7:]
# Use PIL's ImageColor.getrgb() to convert hex string to a rgb tuple
color = ImageColor.getrgb(color)
img_data.append((x,y,color))
# Keep track of the max x,y vals for to get the width and height of the image
height = max(height, x+1)
width = max(width, y+1)
# Create a new image
background = (0, 0, 0, 255)
img = Image.new('RGB', (width, height), background)
pixels = img.load()
# Set the pixel values from our data
for d in img_data:
pixels[d[0], d[1]] = d[2]
img.save("image.png")
Now it raises:
ValueError: too many values to unpack
How to solve this error?
This worked for me:
from PIL import Image
from PIL import ImageColor
path_to_file = 'test.txt'
img_data = []
height = 0
width = 0
# The first step is to read the file
with open(path_to_file) as f:
lines = f.readlines()
# Strip off new lines
lines = [x.strip('\n') for x in lines]
for line in lines:
x,y = line[:-7].split(',')
# I'm assuming from the data that the x,y vals start at 1,1. Subtract 1 from each value so they are zero indexed.
x = int(x) - 1
y = int(y) - 1
color = line[-7:]
# Use PIL's ImageColor.getrgb() to convert hex string to a rgb tuple
color = ImageColor.getrgb(color)
img_data.append((x,y,color))
# Keep track of the max x,y vals for to get the width and height of the image
height = max(height, y)
width = max(width, x)
# Create a new image
background = (0, 0, 0, 255)
img = Image.new('RGB', (width + 1, height + 1), background)
pixels = img.load()
# Set the pixel values from our data
for d in img_data:
pixels[d[0], d[1]] = d[2]
img.save("image.png")

Segmenting Image In Fixed Blocks

Its not about cropping an image in OpenCV. I know how to do it, for example: Image[200:400, 100:300] # Crop from x, y, w, h -> 100, 200, 300, 400. What I am trying to do is create multiple segments of the Image, which do not exceed Image's Width/Height obviously.
So precisely, if an Image is 720x640 resolution,and I need to split this image in multiple blocks, say it 100x100 Fixed blocks, so how to achieve this exactly in OpenCV using Python?
import cv2
def segmentize (image_path, segment_width=200, segment_height=50):
# Croping Formula ==> y:h, x:w
idx, x_axis, x_width, = 1, 0, segment_width
y_axis, y_height = 0, segment_height
img = cv2.imread(image_path)
height, width, dept = img.shape
while y_axis <= height:
while x_axis <= width:
crop = img[y_axis:y_height, x_axis:x_width]
x_axis=x_width
x_width+=segment_width
cropped_image_path = "crop/crop%d.png" % idx
cv2.imwrite(cropped_image_path, crop)
idx+=1
y_axis += segment_height
y_height += segment_height
x_axis, x_width = 0, segment_width

Categories

Resources