-1

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;
}
wohlstad
  • 12,661
  • 10
  • 26
  • 39
Tushar Khurana
  • 31
  • 1
  • 2
  • 7
  • 1
    You'll be glad to hear you don't need anyone's help to figure this out, just a tool you already have: your debugger! This is exactly what a debugger is for. It [runs your program, one line at a time, and shows you what's happening](https://stackoverflow.com/questions/25385173/), this is something that's every C++ developer must know how to do. With your debugger's help you'll able to quickly find all problems in this and all future programs you write, without having to ask anyone for help. Have you tried using your debugger, already? If not, why not? What did your debugger show you? – Sam Varshavchik Dec 06 '22 at 13:24
  • 2
    _"Process terminated with status -1073741819"_ - That's something I'd expect from this program if opening the file fails (in addition to the problem with swapping the coordinates that wohlstad mentions below). – Ted Lyngmo Dec 06 '22 at 14:00

1 Answers1

3

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;.

wohlstad
  • 12,661
  • 10
  • 26
  • 39