Reputation: 11
I am attempting to create an algorithm that locates the white pixels in a column of a binary image, and then adds the y co-ordinates/column number of each white pixel and divides this value by the number of white pixels in the column, in order to get the "mean/middle positioned" white pixel in the column. And this returns an (x,y) co-ordinate that can be plotted. This process repeats for each column in the image and each time sy sets back to 0.
The end goal is instead of having a lines that are multiple pixels thick/wide, as shown in the image's numpy arraycurrent line multiple thicks wide array, I have lines that are just one pixel wide, whilst mantaining the original shape. I planned on doing this by selecting the "mean positioned white pixel in each column". I will then use these pixels to obtain x and y co-ordinates to plot. Here is what I have
sx = x = img.shape[1]
sy = 0
whitec = cv2.countNonZero(img.shape[1])
arrayOfMeanY = [] #array to place (x,y) co-ordinate in
#Select column to iterate
for x in range(img.shape[1]):
# iterating through individual items in the column
for y in range(img.shape[0]):
# Checking for white pixels
pixel = img[x,y]
if pixel == 255:
# Then we check the y values of the white pixels in the column and add them all up
sy = sy+y
whitec +=1
# Doing the calculation for the mean and putting it into the meanY list
sy = sy/whitec
y = sy
print img[x,y]
array.append(y)
cv2.waitKey(0)
# reset sy to 0 for the next column
sy = 0
My issue is I recieve this error when I run the code:
File "<ipython-input-6-e4c2225ff632>", line 27, in <module>
whitec = cv2.countNonZero(img.shape[1]) #n= number of white pixels
in the column
TypeError: src is not a numpy array, neither a scalar
How do I rectify this issue, and once once this issue is rectified will my coding do what I described above.
Upvotes: 0
Views: 277
Reputation: 23032
No need for loops here. With numpy
you hardly ever need to loop over individual pixels.
Instead, create a function which takes the mean of the locations of the non-zero pixels for each column (I converted to np.intp
to index the image; you could just cast with int()
but np.intp
is what Numpy uses for indexing arrays so, it's slightly more appropriate).
def avgWhiteLocOverCol(col):
return np.intp(np.mean(np.where(col)))
Then you can simply apply the function along all columns with np.apply_along_axis()
.
avgRows = np.apply_along_axis(avgWhiteLocOverCol, 0, img)
For example, let's create an image with white pixels on the middle row and on the diagonal:
import numpy as np
import cv2
img = np.eye(500)*255
img[249,:] = 255
cv2.imshow('',img)
cv2.waitKey(0)
Then we can apply the function over each column, which should give a line with half the slope:
def avgWhiteLocOverCol(col):
return int(np.mean(np.where(col)))
avgRows = np.apply_along_axis(avgWhiteLocOverCol, 0, img)
avgIndImg = np.zeros_like(img)
avgIndImg[avgRows,range(img.shape[1])] = 255
cv2.imshow('',avgIndImg)
cv2.waitKey(0)
Upvotes: 1