Iris.Hardwood
Iris.Hardwood

Reputation: 11

algorithm that finds the "mean positioned" white pixel in a column and repeats the process for each column

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

Answers (1)

alkasm
alkasm

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)

Example image

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)

Example output image

Upvotes: 1

Related Questions