8

I am new to openCV and Python and a have a question concerning it. I am trying to find the amount of blue pixels of a picture so i can use them as a threshold in order to compare other pictures with it. I have tried looking through the documentation but i couldn't find anything helpful yet.

Can anyone give a hint or some help?


BLUE_MAX = np.array([0, 0, 200], np.uint8)
BLUE_MIN = np.array([50, 50, 255], np.uint8)

dst = cv.inRange(img, BLUE_VALUE_MIN, BLUE_VALUE_MAX)
no_blue = cv.countNonZero(dst)

print('The number of blue pixels is: ' + str(no_blue))

-So based on your recommendation I built the following function but all I get when I run it is a blank picture.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
akortex
  • 5,067
  • 2
  • 25
  • 57
  • 1
    Welcome to Stack Overflow! We're unlikely to be able to help you without seeing more context. Could you post your actual code here and [describe what you've tried](http://whathaveyoutried.com)? Be sure also to check the [question checklist](http://meta.stackexchange.com/questions/156810/stack-overflow-question-checklist). Thanks! – Christian Ternus Oct 27 '13 at 20:29
  • 1
    You need to define what you mean by "blue pixel". – Hannes Ovrén Oct 27 '13 at 20:58

2 Answers2

10

For counting blue pixel in a RGB image you can simply do the following

  1. Inrange the source image to filter out blue component to a binary image.
  2. Count non zero pixel in the binary image using the function countNonZero.

You can refer below C++ code for how to do it

#include <stdio.h>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;

int main()
{
    Mat src,dst;
    src = imread("rgb1.jpg",1);
    inRange(src, Scalar(200,0,0), Scalar(255,50,50), dst); //In range with approximate blue range
    cout<<"No of blue pixels---->"<<countNonZero(dst)<<endl;
    imshow("src",src); 
    imshow("out",out);

    waitKey(0);

    return 0;
}

Edit:-

Here is the working python code

import cv2
import numpy as np

img = cv2.imread("bgr.png")
BLUE_MIN = np.array([0, 0, 200], np.uint8)
BLUE_MAX = np.array([50, 50, 255], np.uint8)

dst = cv2.inRange(img, BLUE_MIN, BLUE_MAX)
no_blue = cv2.countNonZero(dst)
print('The number of blue pixels is: ' + str(no_blue))
cv2.namedWindow("opencv")
cv2.imshow("opencv",img)
cv2.waitKey(0)

Hope this is what you looking for.....

Edit2:-

As @ kigurai commented below OpenCV consider image in BGR order and I gave wrong order for BLUE_MIN and BLUE_MAX array. So in the above code the lines

 BLUE_MIN = np.array([0, 0, 200], np.uint8)    
 BLUE_MAX = np.array([50, 50, 255], np.uint8)  

should changed to

 BLUE_MIN = np.array([200, 0, 0], np.uint8) // minimum value of blue pixel in BGR order
 BLUE_MAX = np.array([255, 50, 50], np.uint8)// maximum value of blue pixel in BGR order
Haris
  • 13,645
  • 12
  • 90
  • 121
  • Thanks for the help, i think i am starting to get this but can you explain what the inRange() line does exactly? – akortex Oct 28 '13 at 12:38
  • inRange() Checks if array elements lie between the two Scalar supplied as argument. Where first Scalar is the lowest possible RGB value of blue and the second Scalar is the highest possible RGB value of blue. So the inRange() checks whether your source image contains pixel value in between these scalar and if so it will set the corresponding pixel to maximum value in your destination image. – Haris Oct 28 '13 at 12:54
  • So basically what it does is to take the input picture, scan through it, determine which pixels lie between the lowest and the highest blue value, and the set that pixel to the highest possible blue value. In the count non zero function, aren't you supposed to use the output image from the inRange function? – akortex Oct 29 '13 at 18:23
  • Sorry coding mistake, you have to pass the result of inRange() to countNonZero. I will edit my answer. – Haris Oct 30 '13 at 04:37
  • I did the same thing before you edited your answer, but the code still won't work correctly. I am giving the program two different pictures and i get zero as a result. I think it has something to do with the min and max blue values. Did it work for you? – akortex Oct 31 '13 at 16:29
  • Since OpenCV by default loads images in BGR-format and not RGB, shouldn't the BLUE_MIN and BLUE_MAX be reversed? – Hannes Ovrén Nov 19 '13 at 14:41
  • Yes, you are correct BLUE_MIN and BLUE_MAX should be in BGR order. Actually I tested the above code with an image containing equal blue, green and red portion that's why I got the result. Anyway sorry for the mistake I will edit my answer. – Haris Nov 20 '13 at 05:13
3

If you are looking for blue pixels in a photographed image, I recommend converting to HSV colour space first and then look for the color range for blue. This way, you can ignore the brightness component.

See this question for colour ranges in HSV color space.

Community
  • 1
  • 1
Totoro
  • 3,398
  • 1
  • 24
  • 39