Reputation: 93
I am trying to count total number of white pixels in the following image:
But with my code, I get this error
src is not a numpy array, neither a scalar.
This is my code:
img=cv2.imread(filename,1)
TP= width * height
white= TP - cv2.countNonZero(img[1])
print "Dimensions:", img.size, "Total pixels:", TP, "White", white
Upvotes: 6
Views: 43403
Reputation: 21203
One has to have a clear understanding of cv2.countNonZero()
before using it.
(-215:Assertion failed) cn == 1
The following is a binary image:
spot_img = cv2.imread('spots.jpg', 0)
binary_img = cv2.threshold(spot_img, 127, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
cv2.countNonZero(binary_img)
5
There are 5 non zero pixels in the image. And given that the image is binary we can conclude there are 5 white pixels (pixel value = 255)
code_img = cv2.imread(r'C:\Users\524316\Desktop\Stack\m1.png', 0)
cv2.countNonZero(code_img)
5937
In the above gray scale image there are 5937 non zero pixels in the image. And that includes pixel values between [1 - 255]
To get only the count of white pixels [255], use np.sum()
as mentioned above:
np.sum(code_img == 255)
5792
To get the count of a particular pixel value, use the same as above
Upvotes: 2
Reputation: 388
I am using map data structure it will give you different pixels from an image and also their count. You can use any other data structure, you are comfortable with.
map<Vec3b, int> palette;
for (int y = 0; y<im.rows; y++) {
for (int x = 0; x<im.cols; x++)
{
Vec3b color = im.at<Vec3b>(Point(x, y));
if (palette.count(color) == 0)
{
palette[color] = 1;
}
else
{
palette[color] = palette[color] + 1;
}
}
}
Upvotes: 2
Reputation: 23012
Notice that Image
is capitalized...in PIL, Image
is a class. The actual image data is one of the many properties inside the class, and PIL does not use numpy arrays. Thus, your image is not a numpy array. If you want to convert to a numpy array, simply encase the image as an array:
img = np.array(img)
If you read the image with OpenCV, then it already comes as a numpy array.
img = cv2.imread(filename)
Also note that the ordering of channels is different in PIL than OpenCV. In PIL, images are read as RGB order, while in OpenCV, they are in BGR order. So if you read with PIL but display with OpenCV, you'll need to swap the channels before displaying.
Edit: also, check the OpenCV docs for countNonZero()
. This function only works on single channel arrays, so you'll need to either convert the image to grayscale, or decide how you want to count a zero. You can also just use numpy just by np.sum(img == 0)
to count the number of zero values, or np.sum(img > 0)
to count non-zero values. For a three channel array, this will count all the zeros in each channel independently. If you want to only include ones that are zero in all three colors, you can do a number of things---the simplest is probably to add all the channels together into one 2D array, and then do the same as above.
Edit2: also, your code right now is counting the number of black pixels, not white. countNonZero()
will return the number of all pixels greater than 0. Then you subtract that off the total number of pixels...which will give you only the black pixels. If you just want to count the number of white pixels, np.sum(img == 255)
.
Edit3: So with your image, this code works fine:
import cv2
import numpy as np
img = cv2.imread('img.png', cv2.IMREAD_GRAYSCALE)
n_white_pix = np.sum(img == 255)
print('Number of white pixels:', n_white_pix)
Number of white pixels: 5
Note here that cv2.IMREAD_GRAYSCALE
is just equal to 0, but this is more explicit.
Upvotes: 19