pixelthread
pixelthread

Reputation: 93

Count total number of white pixels in an image

I am trying to count total number of white pixels in the following image:

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

Answers (3)

Jeru Luke
Jeru Luke

Reputation: 21203

One has to have a clear understanding of cv2.countNonZero() before using it.

  • It can be used only with an image of single channel. In other words, an image with only two dimensions (width and height). When used with a 3-channel image you would face an assertion error: (-215:Assertion failed) cn == 1
  • As the name suggests, it counts number of pixels within an image having pixel value greater than 0, i.e. pixel values within the range [1 - 255]

Example 1:

The following is a binary image:

enter image description here

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)

Example 2:

enter image description here

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

Muskan Agarwal
Muskan Agarwal

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

alkasm
alkasm

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

Related Questions