Home > Software design >  How to get negative of each channel (Red, Green, Blue) in RGB image?
How to get negative of each channel (Red, Green, Blue) in RGB image?

Time:12-15

I am trying to get negative of negative of each channel (Red, Green, Blue) in RGB image.
Simply put :

  1. If value of red channel in an RGB image is 'r', I am looking to get r'=255-r.
  2. Repeat this process for green and blue as well.
  3. Finally merge r',g' and b' to display the image.

Below is the code I have written but it gives:

Process terminated with status -1073741819

as output. Also please see detailed output.

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

int main()
{
   Mat myImage;//declaring a matrix to load the image//
   Mat different_Channels[3];//declaring a matrix with three channels//
   String imgPath = "C:/Users/tusha/Desktop/ResearchPractise/testNegativeImage/RGB.jpg";
   myImage= imread(imgPath,IMREAD_UNCHANGED);//loading the image in myImage matrix//
   split(myImage, different_Channels);//splitting images into 3 different channels//
   Mat b = different_Channels[0];//loading blue channels//
   Mat g = different_Channels[1];//loading green channels//
   Mat r = different_Channels[2];//loading red channels//
   //for red channel
   for (int y = 0; y < myImage.rows; y  ) {
        for (int x = 0; x < myImage.cols; x  ) {
            //Retrieving the values of a pixel
            int pixelr = r.at<uchar>(x,y);
            pixelr = 255-pixelr;
            r.at<uchar>(x,y)=pixelr;
            }
   }

   //for green channel
   for (int y = 0; y < myImage.rows; y  ) {
        for (int x = 0; x < myImage.cols; x  ) {
            //Retrieving the values of a pixel
            int pixelg = g.at<uchar>(x,y);
            pixelg = 255-pixelg;
            g.at<uchar>(x,y)=pixelg;
            }
   }
   //for blue channel
   for (int y = 0; y < myImage.rows; y  ) {
        for (int x = 0; x < myImage.cols; x  ) {
            //Retrieving the values of a pixel
            int pixelb = b.at<uchar>(x,y);
            pixelb = 255-pixelb;
            b.at<uchar>(x,y)=pixelb;
            }
   }
   vector<Mat> channels;
   channels.push_back(r);
   channels.push_back(g);
   channels.push_back(b);
   Mat negImage;
   merge(channels,negImage);
   cout<<"Negative image";
   namedWindow("Negative",WINDOW_NORMAL);
   imshow("Negative",negImage);
   return 0;
}

CodePudding user response:

The main issue:
As you can see in the cv::Mat::at documentation, you should first pass the col (i.e. your y coordinate), and then the row (i.e. your x coordinate).

Therefore all the 6 lines referring to:

at<uchar>(x,y)

Should be changed to:

at<uchar>(y,x)

Assuming your image is not a square, inverting the coordinated as you did is not only semantically wrong but will also result in access via invalid indices (causing access violation).

Regarding the result display:
You can also remove the WINDOW_NORMAL argument you pass to cv::namedWindow in order to see the result image in its actual size.
In addition you should add a call to cv::waitKey (e.g. cv::waitKey(0);) after it to keep the window opened and process GUI events.

Note that using cv::Mat::at to traverse all pixels is quite inefficient. A more efficient approach would be to use cv::Mat::ptr per row to get a pointer to the row data, and then traverse it using pointer arithmetics.

A side note: better to avoid using namespace std - see here Why is "using namespace std;" considered bad practice?. A similar argument can be applied to using namespace cv;.

  • Related