我需要找到用户手中的文档边缘。
1)来自相机的原始图像:
3)然后我变得模糊:
3)使用Canny查找图像的边缘:
4)并使用dilate:
如您在最后一张图像上看到的,地图周围的轮廓被撕裂,轮廓未确定。我的错误是什么?如何解决该问题以便完全确定文档的轮廓?
这是我如何执行的代码:
final Mat mat = new Mat();
sourceMat.copyTo(mat);
//convert the image to black and white
Imgproc.cvtColor(mat, mat, Imgproc.COLOR_BGR2GRAY);
//blur to enhance edge detection
Imgproc.GaussianBlur(mat, mat, new Size(5, 5), 0);
if (isClicked) saveImageFromMat(mat, "blur", "blur");
//convert the image to black and white does (8 bit)
int thresh = 128;
Imgproc.Canny(mat, mat, thresh, thresh * 2);
//dilate helps to connect nearby line segments
Imgproc.dilate(mat, mat,
Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3, 3)),
new Point(-1, -1),
2,
1,
new Scalar(1));
答案 0 :(得分:1)
此答案基于我上面的评论。如果有人拿着文档,则看不到用户手后面的边缘。因此,任何用于检测文档轮廓的方法都必须对边缘的某些缺失部分具有鲁棒性。
我建议使用Hough变换的变体来检测文档。 Wikipedia article涉及到Hough变换,听起来听起来很吓人(就像Wikipedia经常在数学主题上一样),但是不要灰心,实际上它们并不太难理解或实现。
原始的Hough变换检测到图像中的直线。如this OpenCV tutorial中所述,图像中的任何一条直线都可以由2个参数定义:线距原点的角度θ和距离 r 。因此,您可以量化这两个参数,并为图像中可能存在的每条线创建一个带有一个单元的2D数组。 (使用的量化越精细,将需要的数组越大,但是找到的行的位置越准确。)将数组初始化为零。然后,对于Canny检测到的边缘的每个像素,确定该像素可能属于的每条线(θ, r ),并增加相应的斌处理完所有像素后,对于每个仓,您将获得在与该仓相对应的行上检测到多少像素的计数。即使行的某些部分丢失,足够高的计数也可能表示图像中的实线。因此,您只需扫描垃圾箱即可找到超过阈值的垃圾箱。
OpenCV包含用于直线和圆形的霍夫检测器,但不包含用于矩形的霍夫检测器。您可以使用行检测器并检查形成文档边缘的4条线。或者您可以编写自己的矩形Hough检测器,也许可以使用论文Jung 2004进行启发。矩形至少具有5个自由度(2D位置,比例,长宽比和旋转角度),并且5D阵列的内存需求显然增长得很快。但是,由于每个参数的范围都是有限的(即,文档的纵横比是已知的,并且您可以假定文档将居中且不会旋转太多),所以这可能是可行的。