0

Hi I found an algorithm online which produces the results I need, I have implemented this algorithm into my program. However, I keep getting an Access violation reading location error. I'm not sure why this is? I should say I am a newbie at C++ and using libraries such as OpenCV

My main function is this:

    int main(int argc, char** argv)
{
cout << "Welcome to the Image to Graph function"<< endl;;

cv::Mat src = cv::imread("M:/Documents/Internship Project/Dr_V_Project/Output Images/FC 100x2_no_holes100.png");
if (!src.data)
    return -1;

cv::Mat bw;
cv::cvtColor(src, bw, CV_BGR2GRAY);
thinningGuoHall(bw);

waitKey(0);
return 0;
}

The other functions of this program are:

void thinningGuoHallIteration(cv::Mat& im, int iter)
{
cv::Mat marker = cv::Mat::zeros(im.size(), CV_8UC1);

for (int i = 1; i < im.rows; i++)
{
    for (int j = 1; j < im.cols; j++)
    {
        uchar p2 = im.at<uchar>(i - 1, j);
        uchar p3 = im.at<uchar>(i - 1, j + 1);
        uchar p4 = im.at<uchar>(i, j + 1);     // ERROR SEEMS TO OCCUR HERE!
        uchar p5 = im.at<uchar>(i + 1, j + 1);
        uchar p6 = im.at<uchar>(i + 1, j);
        uchar p7 = im.at<uchar>(i + 1, j - 1);
        uchar p8 = im.at<uchar>(i, j - 1);
        uchar p9 = im.at<uchar>(i - 1, j - 1);

        int C = (!p2 & (p3 | p4)) + (!p4 & (p5 | p6)) +
            (!p6 & (p7 | p8)) + (!p8 & (p9 | p2));
        int N1 = (p9 | p2) + (p3 | p4) + (p5 | p6) + (p7 | p8);
        int N2 = (p2 | p3) + (p4 | p5) + (p6 | p7) + (p8 | p9);
        int N = N1 < N2 ? N1 : N2;
        int m = iter == 0 ? ((p6 | p7 | !p9) & p8) : ((p2 | p3 | !p5) & p4);

        if (C == 1 && (N >= 2 && N <= 3) && m == 0)
            marker.at<uchar>(i, j) = 1;
    }
}

im &= ~marker;
}

void thinningGuoHall(cv::Mat& im)
{
im /= 255;

cv::Mat prev = cv::Mat::zeros(im.size(), CV_8UC1);
cv::Mat diff;

do {
    thinningGuoHallIteration(im, 0);
    thinningGuoHallIteration(im, 1);
    cv::absdiff(im, prev, diff);
    im.copyTo(prev);
} while (cv::countNonZero(diff) > 0);

im *= 255;
}

Could someone help me resolve this error?

AM11
  • 13
  • 1
  • Well, what did you observe when stepping through your code with the debugger? –  Jan 26 '18 at 11:36
  • This might have to do with how arrays work in C++. If you have an array of `col` elements, valid indices are 0 ... `col - 1`. Your (both) loops start with `1`. Hence, `i - 1` and `j - 1` are OK. But, your loops stop at `im.rows` and `im.cols`. E.g. `j + 1` can become `im.col` and results in a possible out of bound access. You may prevent this e.g. by changing the loops to `i + 1 < im.rows` and `j + 1 < im.cols`. – Scheff's Cat Jan 26 '18 at 11:36

1 Answers1

1

Very easy: Your access is out of bounds.

You iterate i and j up to im.rows-1 and im.cols-1, respectively. When j is im.cols-1 the first time, the line

uchar p4 = im.at<uchar>(i, j + 1);

becomes

uchar p4 = im.at<uchar>(1, im.cols);

which is out of bounds. Change the loop headers to

for (int i = 1; i+1 < im.rows; i++)
{
    for (int j = 1; j+1 < im.cols; j++)
    {

and you won't get the access violation.

Demosthenes
  • 1,515
  • 10
  • 22
  • Thank you very much, it works. However I don't understand why my colleagues implementation of the same code works? (Before fix). Thanks again! – AM11 Jan 26 '18 at 11:48
  • This is important about C++ programming: If something does not crash this does not mean that it is free of errors. A term you find often is @AM11 [**Undefined Behavior**](https://stackoverflow.com/a/4105123/1505939). In short: Wrong code can cause anything: no visible effect, wrong behavior, crash, or any other exotic effect, e.g. ["make demons fly out of your nose."](http://catb.org/jargon/html/N/nasal-demons.html). – Scheff's Cat Jan 26 '18 at 12:00