Detecting a hue in a photo and turning all other pixels black

Your first problem will be, that gray/black/white pixels have an undefined Hue value too that can be in red range. You’ll need to check the Saturation value too to determine if it’s gray or colored.

I don’t know any specific opencv command for your case but you can do it using the following algorithm:

  • check if Hue is bigger than (360-15) and smaller than (0+15)
  • check if the color is saturated
  • if both then copy it to a black image.

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
    int delta = 15; //red hue is around 0, so we need 0 +- 15
    Mat BGR, HSV,output;    
    Mat mask,maskL,maskG,maskS;
    std::vector <Mat> channels; //H,S,V channels 

    BGR= imread("samples/data/ml.png");  //read image as BGR color space, ml.png can be found somewhere in your opencv directory
    cvtColor(BGR, HSV, COLOR_BGR2HSV); //convert it to HSV color space. Hue will be 0...180 because 8-bit values can only be 0.255    
    split(HSV, channels); //channels[0]=H[0..180], channels[1]=S [0..255], channels[0]=V[0..255], 

    output = Mat(BGR.size(), BGR.type(), Scalar(0)); //create empty output and set all pixels to black

    //as Hue is an angle, you could do weird trigonometric sinus/cosinus euler stuff to make it more scientific, but this is easier and faster for your problem
    compare(channels[0], Scalar(  0 + delta/2.0), maskL, CMP_LE); //if H[x,y]<=delta then set pixel in mask
    compare(channels[0], Scalar(180 - delta/2.0), maskG, CMP_GE); //if H[x,y]>=(360-delta) then set pixel in mask
    bitwise_or(maskL, maskG, mask); //if one of them is set, take it

    //gray and white have undefined Hue values so check Saturation too
    compare(channels[1], Scalar(128), maskS, CMP_GE); //if Saturation>128 then set pixel in mask, you'll have to find a good threshold for this yourself
    bitwise_and(mask, maskS, mask); //only take pixels that are in range AND have a Saturation value above threshold

    BGR.copyTo(output, mask); //copy only masked pixels to output image

    //show output
    imshow("Input", BGR);
    imshow("Output", output);
    imshow("H", channels[0]);
    imshow("S", channels[1]);
    imshow("V", channels[2]);
    waitKey(0);
}