C++ OpenCV实现Guo-Hall细化算法时遇Access violation错误求助
Hey there! Let's break down why you're hitting that "Access violation reading location" error and how to fix it.
The Root Cause: Out-of-Bounds Memory Access
The error happens at uchar p4 = im.at<uchar>(i, j + 1); (and other similar lines like p5 = im.at<uchar>(i + 1, j + 1);) because you're trying to access pixels outside the valid bounds of your OpenCV Mat.
OpenCV Mat objects use 0-based indexing:
- Rows range from
0toim.rows - 1 - Columns range from
0toim.cols - 1
Look at your original loop conditions:
for (int i = 1; i < im.rows; i++) { for (int j = 1; j < im.cols; j++) {
When i reaches im.rows - 1 (the last valid row), i + 1 becomes im.rows—which is beyond the Mat's row limits. Same for j: when j hits im.cols - 1, j + 1 is im.cols, which is out of bounds. This invalid memory access triggers the access violation.
The Fix: Adjust Loop Bounds
Modify your loop termination conditions to stop one step before the last row/column, so i+1 and j+1 never go out of bounds:
void thinningGuoHallIteration(cv::Mat& im, int iter) { cv::Mat marker = cv::Mat::zeros(im.size(), CV_8UC1); // Update loop bounds to avoid out-of-bounds access for (int i = 1; i < im.rows - 1; i++) { for (int j = 1; j < im.cols - 1; 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); 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); // Rest of your logic stays unchanged 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; }
Quick Additional Check
Make sure your input bw (the grayscale image converted from src) is properly binarized before passing it to thinningGuoHall. Right now you're doing im /= 255; which assumes all pixels are either 0 or 255. If your grayscale image has intermediate values, add a threshold step to get a proper binary image:
cv::cvtColor(src, bw, CV_BGR2GRAY); // Add this line to binarize the image cv::threshold(bw, bw, 127, 255, cv::THRESH_BINARY); thinningGuoHall(bw);
内容的提问来源于stack exchange,提问作者AM11

