You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中OpenCV基于ROI的图像二值化算法报错求助

基于ROI的图像二值化OpenCV异常排查

问题重现

在Java中使用OpenCV实现分块ROI图像二值化时,在Mat roi = new Mat(gray, roi_rect)行抛出断言异常,异常信息如下:

OpenCV(4.7.0-dev) Error: Assertion failed (0 <= _colRange.start && _colRange.start <= _colRange.end && _colRange.end <= m.cols) in cv::Mat::Mat, file C:\GHA-OCV-2_work\ci-gha-workflow\ci-gha-workflow\opencv\modules\core\src\matrix.cpp, line 776
Exception in thread "main" CvException [org.opencv.core.CvException: cv::Exception: OpenCV(4.7.0-dev) C:\GHA-OCV-2_work\ci-gha-workflow\ci-gha-workflow\opencv\modules\core\src\matrix.cpp:776: error: (-215:Assertion failed) 0 <= _colRange.start && _colRange.start <= _colRange.end && _colRange.end <= m.cols in function 'cv::Mat::Mat']

原代码片段:

System.loadLibrary(org.opencv.core.Core.NATIVE_LIBRARY_NAME);
String filename = "path/to/image";
Mat image = Imgcodecs.imread(filename, Imgcodecs.IMREAD_COLOR);
int ch = 255, cw = 255; //---small block
int h = image.rows(), w = image.cols(); //---height vs width
Mat gray = new Mat();
Imgproc.cvtColor(image, gray, Imgproc.COLOR_BGR2GRAY); //--to gray

//-----handle every small block
for (int row = 0; row < h; row += ch) {
    for (int col = 0; col < w; col += cw) {
        Rect roi_rect = new Rect(col, row, cw, ch); //------small block:rectangle
        Mat roi = new Mat(gray, roi_rect);
        Imgproc.adaptiveThreshold(roi, roi, 255, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, 127, 10); //----binarization
        roi.copyTo(gray.submat(roi_rect));//----replace original block
    }
}

HighGui.imshow("binary", gray); 

问题原因

循环中固定使用ch=255和cw=255作为块的宽高,但图像的实际宽/高不一定是255的整数倍。当循环到最后一块时,row + ch会超过图像实际高度h,col + cw会超过图像实际宽度w,导致创建的Rect范围超出了gray矩阵的边界,触发OpenCV的断言检查(要求ROI的起始和结束坐标必须在矩阵合法范围内)。

解决方案

在每次创建ROI矩形前,计算当前块的实际宽高,确保不超出图像边界:

System.loadLibrary(org.opencv.core.Core.NATIVE_LIBRARY_NAME);
String filename = "path/to/image";
Mat image = Imgcodecs.imread(filename, Imgcodecs.IMREAD_COLOR);
int ch = 255, cw = 255; //---small block
int h = image.rows(), w = image.cols(); //---height vs width
Mat gray = new Mat();
Imgproc.cvtColor(image, gray, Imgproc.COLOR_BGR2GRAY); //--to gray

//-----handle every small block
for (int row = 0; row < h; row += ch) {
    // 计算当前块的实际高度,避免超出图像底部
    int currentBlockHeight = Math.min(ch, h - row);
    for (int col = 0; col < w; col += cw) {
        // 计算当前块的实际宽度,避免超出图像右边界
        int currentBlockWidth = Math.min(cw, w - col);
        Rect roi_rect = new Rect(col, row, currentBlockWidth, currentBlockHeight);
        Mat roi = new Mat(gray, roi_rect);
        // adaptiveThreshold直接修改roi(gray的子矩阵),无需额外copyTo
        Imgproc.adaptiveThreshold(roi, roi, 255, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, 127, 10);
    }
}

HighGui.imshow("binary", gray);
HighGui.waitKey(0); // 补充waitKey确保窗口正常显示

额外说明:原代码中的roi.copyTo(gray.submat(roi_rect))是多余的,因为roi本身是gray的子矩阵(共享内存),调用adaptiveThreshold修改roi时,已经直接修改了gray中对应的区域。

内容的提问来源于stack exchange,提问作者biotech7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 20:52:13