1

I've been reading about opencv and I've been doing some exercises, in this case I want to perform an image equalization, I have implemented the following code, but when I execute it I get the following error:

"Segmentation fault (core dumped)"

So I have no idea what is due.

The formula I am trying to use is the following:

equalization

The code is the following:

 #include <opencv2/opencv.hpp>
 #include <opencv2/highgui/highgui.hpp> 
 #include <stdio.h>

 using namespace cv;
 using namespace std;

 void equalization(cv::Mat &image,cv::Mat &green, int m) {
 Mat eqIm;
 int nl= image.rows; // number of lines

int nc= image.cols * image.channels();
for (int j=0; j<nl; j++) {

    uchar* data= image.ptr<uchar>(j);
    uchar* data2= green.ptr<uchar>(j);
    uchar* eqIm= green.ptr<uchar>(j);

    for (int i=0; i<nc; i++) {

        eqIm[i]= data[i]+m-data2[i];

    }
 }
 cv::imshow("Image",eqIm);
 imwrite("eqIm.png",eqIm);
 }

float mean(cv::Mat &image){
   cv:Scalar tempVal = mean( image );
   float myMAtMean = tempVal.val[0];
   cout << "The value is " << myMAtMean;
 }

 int main(int argc, char** argv ){
 Mat dst;
 Mat image= cv::imread("img.jpg");
 Mat green= cv::imread("green.jpg");

 cv::imshow("Image",image);
 float m= mean(image);

 equalization(image,green,m);
 cv::namedWindow("Image");
 cv::imshow("Image",image);
 imwrite("equalizated.png",dst);
 waitKey(0);
 return 0;

}

and the image "Equalization.png" that is written contains nothing

nneJZ03
  • 49
  • 2
  • In addition to pepperjack's answer: [Avoid `using namespace`](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) | Don't include what you don't need (why `stdio.h`?) | When compiling, enable warnings and treat them as errors. | One would expect a function named `mean` to calculate and return the mean, not print it to console and cause UB by omitting a return statement. | Similarly, one would expect `equalization` to actually return the equalized image, rather than saving it to hardcoded file, popping up window, discarding the result and expecting... – Dan Mašek Nov 20 '17 at 14:25
  • ... the user (as in programmer using the function) to remember to call `waitKey` afterwards to make the visualization work. ([POLA](https://en.wikipedia.org/wiki/Principle_of_least_astonishment)) | Finally, familiarize yourself with the OpenCV documentation, especially of the fundamental types such as `cv::Mat` and the operations available on those. Then use those high level abstractions. For example, the body of `equalization` is basically `Mat eqIm = image + m - green;`. – Dan Mašek Nov 20 '17 at 14:29

1 Answers1

2

You never initialized Mat eqIm, so when you do cv::imshow("Image", eqIm); imwrite("eqIm.png", eqIm); there is nothing in the mat. https://docs.opencv.org/2.4/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.html

Also, I should note that you have 2 variables of eqIm. That may be part of the confusion.

One last thing, in your mean function, you may end up with a recursive function. You should specify what mean function you are using in the mean function you create, i.e.

float mean(cv::Mat &image) {
cv:Scalar tempVal = cv::mean(image);
    float myMAtMean = tempVal.val[0];
    cout << "The value is " << myMAtMean;
    return myMAtMean;
}

The following is something closer to what you are looking for in your equalization function.

void equalization(cv::Mat &image, cv::Mat &green, int m) {
    Mat eqIm(image.rows,image.cols,image.type());
    int nl = image.rows; // number of lines
    int nc = image.cols * image.channels();
    for (int j = 0; j<nl; j++) {// j is each row
        for (int ec = 0; ec < nc; ec++) {//ec is each col and channels
                eqIm.data[j*image.cols*image.channels() + ec] = image.data[j*image.cols*image.channels() + ec] + m - green.data[j*image.cols*image.channels() + ec];
        }
    }
    cv::imshow("Image", eqIm);
    imwrite("eqIm.png", eqIm);
}

I do j*image.cols*image.channels() to step through the entire size of j lines (the number of columns times the number of channels per pixel).

pepperjack
  • 673
  • 6
  • 20
  • I run this code but i get this error : OpenCV Error: Assertion failed (size.width>0 && size.height>0) in imshow, file /opt/opencv/modules/highgui/src/window.cpp, line 331 terminate called after throwing an instance of 'cv::Exception' what(): /opt/opencv/modules/highgui/src/window.cpp:331: error: (-215) size.width>0 && size.height>0 in function imshow Aborted (core dumped) I dont understant what do you do in this step eqIm.data[j*image.cols*image.channels() + ec] = image.data[j*image.cols*image.channels() + ec] + m - green.data[j*image.cols*image.channels() + ec]; Why eqIm.data? – Colours123 Nov 20 '17 at 02:23
  • @Colours123 Try replacing the main loop with `int main(int argc, char** argv) { Mat image = cv::imread("img.jpg"); Mat green = cv::imread("green.jpg"); cv::imshow("Image", image); float m = mean(image); equalization(image, green, m); cv::namedWindow("Image"); cv::imshow("Image", image); waitKey(0); return 0; }`. The old code had a Mat called `dst` in it that may be causing problems when it is being saved, since it also isn't assigned. *One more thing...* as with your original code, both of the input images MUST be of the same format and size. – pepperjack Nov 20 '17 at 03:19
  • @Colours123 `eqIm.data` gives us a pointer to the interleaved channel data of the image (the top row example here: https://i.stack.imgur.com/LNJPs.png ). Then I just run the equalizing equation for each channel in the eqIm, green, and image. – pepperjack Nov 20 '17 at 03:22
  • Ergh... as I was reading back over what I sent I realized I had said "main loop" which is of course completely wrong but it was too late to edit my comment. To clarify, it is only run once. (I had been coding some embedded code where the main function is a loop right before this) – pepperjack Nov 20 '17 at 03:30