Simple highlighting RGB colors with OpenCV

Sometimes, when dealing with object detection one might find that the object is imaged with high values of red, green or blue. For instance this happens with traffic lights, tail lights, traffic signs, etc.

Working with RGB images is the very basic first step. If you look for a red object, keep the Red channel and forget about the others.

For instance, I took my webcam and take a picture of three R, G, and B blocks
If you keep only the Red channel, you get:

This image indeed has high values for the “red” box, but the white regions have high values as well, so the red box could be difficult to detect.

Nevertheless there is a simple trick you can do to isolate better the red color (or any of the others): multiply the red channel by the negative of the other two (that is R * not(G) * not(B)). And you get:

Which is much closer to what I wanted when trying to “detect” red regions in the image.

Here you are the code, hope it’s useful!

void getRed(cv::Mat &srcBGR)
{
  cv::Mat imR(srcBGR.rows, srcBGR.cols, CV_8UC1);
  cv::Mat imG(srcBGR.rows, srcBGR.cols, CV_8UC1);
  cv::Mat imB(srcBGR.rows, srcBGR.cols, CV_8UC1);
  cv::Mat imRboost(srcBGR.rows, srcBGR.cols, CV_8UC1);

  Mat out[] = {imR, imG, imB};
  int from_to[] = {2,0  , 1, 1,  0, 2 };
  cv::mixChannels(&srcBGR, 1, out, 3, from_to, 3);

  cv::bitwise_not(imG, imG);
  cv::bitwise_not(imB, imB);

  cv::multiply(imR, imG, imRboost, (double)1/255);
  cv::multiply(imRboost, imB, imRboost, (double)1/255);

  cv::imwrite("RGB.bmp", srcBGR);
  cv::imwrite("R.bmp", imR);
  cv::imwrite("Ronly.bmp", imRonly);
}
This entry was posted in OpenCV and tagged , . Bookmark the permalink.

3 Responses to Simple highlighting RGB colors with OpenCV

  1. nicolas says:

    Interesting topic. Thanks
    I think there is a small mistake in your code :
    cv::imwrite(“Ronly.bmp”, imRonly);
    should be
    cv::imwrite(“Ronly.bmp”, imRboost);

  2. Jason Burton says:

    Why would you use this method instead of inRange?

    • Hi!

      Yes, cv::inRange can be of help, but I still think this way is better because it doesn’t need to define the range.
      I found this and added my function to try them both. For the image they posted, both functions return the same, but for the one I posted, only my method returned the correct image.

      #include <opencv2/core/core.hpp>
      #include <opencv2/highgui/highgui.hpp>
      #include <opencv2/imgproc/imgproc.hpp>
      #include <iostream>
      using namespace std;
      using namespace cv;

      cv::Mat getRed(const cv::Mat &srcBGR)
      {
      cv::Mat imR(srcBGR.rows, srcBGR.cols, CV_8UC1);
      cv::Mat imG(srcBGR.rows, srcBGR.cols, CV_8UC1);
      cv::Mat imB(srcBGR.rows, srcBGR.cols, CV_8UC1);
      cv::Mat imRDiff(srcBGR.rows, srcBGR.cols, CV_8UC1);

      Mat out[] = {imR, imG, imB};
      int from_to[] = {2,0, 1, 1, 0, 2 };
      cv::mixChannels(&srcBGR, 1, out, 3, from_to, 3);

      cv::bitwise_not(imG, imG);
      cv::bitwise_not(imB, imB);

      cv::multiply(imR, imG, imRDiff, (double)1/255);
      cv::multiply(imRDiff, imB, imRDiff, (double)1/255);

      return imRDiff;
      }

      cv::Mat redFilter(const cv::Mat& src)
      {
      assert(src.type() == CV_8UC3);

      cv::Mat redOnly;
      inRange(src, Scalar(0, 0, 0), Scalar(0, 0, 255), redOnly);

      return redOnly;
      }

      int main(int argc, char** argv)
      {
      Mat input = imread(“/home/marcos/Dropbox/projects/code/rgb/rgb1.jpg”);

      imshow(“input”, input);
      waitKey();

      cv::Mat redOnly = redFilter(input);
      imshow(“cv::inRange”, redOnly);

      cv::Mat redDiff = getRed(input);
      imshow(“diff”, redDiff);
      waitKey();

      return 0;
      }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s