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

基于OpenCV的文档扫描:优化四边形检测问题求助

相机实时文档边缘检测优化求助

背景多变且文档颜色与背景接近时,无法完整检测文档边缘,求解决方案或优化建议。

当前实现代码

预处理与Canny边缘检测

const val CLOSE_KERNEL_SIZE = 5.0
const val BLURRING_KERNEL_SIZE = 5.0
const val DILATE_KERNEL_SIZE = 5.0

val (threshold1, threshold2) = getCannyThresholds(src)

Imgproc.cvtColor(src, src, Imgproc.COLOR_BGR2GRAY)

Imgproc.GaussianBlur(src, src, Size(BLURRING_KERNEL_SIZE, BLURRING_KERNEL_SIZE), 3.0)

Imgproc.Canny(src, destination, threshold1, threshold2)

val dilateKernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, Size(DILATE_KERNEL_SIZE, DILATE_KERNEL_SIZE))
Imgproc.dilate(destination, destination, dilateKernel)

val kernel = Imgproc.getStructuringElement(
    Imgproc.MORPH_ELLIPSE,
    Size(CLOSE_KERNEL_SIZE, CLOSE_KERNEL_SIZE)
)
Imgproc.morphologyEx(
    destination,
    destination,
    Imgproc.MORPH_CLOSE,
    kernel,
    Point(-1.0, -1.0),
    10
)

val preview2 = Mat(destination, Rect(0, 0, destination.width(), destination.height()))
showPreview(preview2)

动态计算Canny阈值

val brightness = Core.mean(mat).`val`[0] / 255

val threshold1 = 10 / brightness
val threshold2 = 40 / brightness

轮廓检测实现

private fun findLargestContours(inputMat: Mat): List<MatOfPoint>? {
    val mHierarchy = Mat()
    val mContourList: List<MatOfPoint> = ArrayList()
    //finding contours - as we are sorting by area anyway, we can use RETR_LIST - faster than RETR_EXTERNAL.
    Imgproc.findContours(inputMat, mContourList, mHierarchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE)

    // Convert the contours to their Convex Hulls i.e. removes minor nuances in the contour
    val mHullList: MutableList<MatOfPoint> = ArrayList()
    val tempHullIndices = MatOfInt()
    for (i in mContourList.indices) {
        Imgproc.convexHull(mContourList[i], tempHullIndices)
        mHullList.add(hull2Points(tempHullIndices, mContourList[i]))
    }
    // Release mContourList as its job is done
    for (c in mContourList) {
        c.release()
    }
    tempHullIndices.release()
    mHierarchy.release()
    if (mHullList.size != 0) {
        mHullList.sortWith { lhs, rhs ->
            Imgproc.contourArea(rhs).compareTo(Imgproc.contourArea(lhs))
        }
        return mHullList.subList(0, min(mHullList.size, FIRST_MAX_CONTOURS))
    }
    return null
}

private fun hull2Points(hull: MatOfInt, contour: MatOfPoint): MatOfPoint {
    val indexes = hull.toList()
    val points: MutableList<Point> = ArrayList()
    val ctrList = contour.toList()
    for (index in indexes) {
        points.add(ctrList[index])
    }
    val point = MatOfPoint()
    point.fromList(points)
    return point
}

问题表现

  • 相机输入画面:
    相机输入画面
  • 检测结果(绿色线条为检测到的轮廓):
    检测结果

目前Canny边缘检测未达预期,文档边缘无法完整被检测到。曾尝试使用Hough Lines,但文档上的文本无法去除,导致检测出大量无效线条。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 22:46:32