I am trying to get negative of negative of each channel (Red, Green, Blue) in RGB image.
Simply put :
- If value of red channel in an RGB image is 'r', I am looking to get r'=255-r.
- Repeat this process for green and blue as well.
- 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;
.