问题描述
我正在使用以下代码检测给定文档的边缘.
private Mat edgeDetection(Mat src) {垫边 = 新垫();Imgproc.cvtColor(src,edges,Imgproc.COLOR_BGR2GRAY);Imgproc.GaussianBlur(edges, edge, new Size(5, 5), 0);Imgproc.Canny(edges, edge, 10, 30);返回边;}
然后我可以通过从中找到最大轮廓来从这个 edges
中找到文档.
我的问题是我可以从以下图片中找到文档:
但不是来自以下图片:
如何改进这种边缘检测?
我使用 Python,但主要思想是一样的.
如果直接对img2做cvtColor:bgr->gray,那肯定失败.因为灰色变得难以区分区域:
相关答案:
这是第二个结果:
Python 代码(Python 3.5 + OpenCV 3.3):
#!/usr/bin/python3# 2017.12.20 10:47:28 CST# 2017.12.20 11:29:30 CST导入 cv2将 numpy 导入为 np##(1) 读入 bgr 空间img = cv2.imread("test2.jpg")##(2) 转换为hsv-space,然后拆分通道hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)h,s,v = cv2.split(hsv)##(3) 使用自适应方法(`THRESH_OTSU`)或固定阈值对 S 通道进行阈值处理th, threshed = cv2.threshold(s, 50, 255, cv2.THRESH_BINARY_INV)##(4) 在threshed S上找到所有的外部轮廓cnts = cv2.findContours(threshed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]画布 = img.copy()#cv2.drawContours(canvas, cnts, -1, (0,255,0), 1)##排序并选择最大的轮廓cnts = sorted(cnts, key = cv2.contourArea)cnt = cnts[-1]## 近似轮廓,所以得到角点arclen = cv2.arcLength(cnt, True)approx = cv2.approxPolyDP(cnt, 0.02* arclen, True)cv2.drawContours(canvas, [cnt], -1, (255,0,0), 1, cv2.LINE_AA)cv2.drawContours(canvas, [approx], -1, (0, 0, 255), 1, cv2.LINE_AA)## 好的,你可以看到结果为 tag(6)cv2.imwrite("detected.png", canvas)
I am using following code to detect edges from given document.
private Mat edgeDetection(Mat src) { Mat edges = new Mat(); Imgproc.cvtColor(src, edges, Imgproc.COLOR_BGR2GRAY); Imgproc.GaussianBlur(edges, edges, new Size(5, 5), 0); Imgproc.Canny(edges, edges, 10, 30); return edges; }
And then I can find the document from this
edges
by finding largest contour from this.My problem is I can find the document from following pic:
but not from following pic:
How can I improve this edge detection?
解决方案I use Python, but the main idea is the same.
If you directly do cvtColor: bgr -> gray for img2, then you must fail. Because the gray becames difficulty to distinguish the regions:
Related answers:
- How to detect colored patches in an image using OpenCV?
- Edge detection on colored background using OpenCV
- OpenCV C++/Obj-C: Detecting a sheet of paper / Square Detection
In your image, the paper is
white
, while the background iscolored
. So, it's better to detect the paper isSaturation(饱和度)
channel inHSV color space
. For HSV, refer to https://en.wikipedia.org/wiki/HSL_and_HSV#Saturation.Main steps:
- Read into
BGR
- Convert the image from
bgr
tohsv
space - Threshold the S channel
- Then find the max external contour(or do
Canny
, orHoughLines
as you like, I choosefindContours
), approx to get the corners.
This is the first result:
This is the second result:
The Python code(Python 3.5 + OpenCV 3.3):
#!/usr/bin/python3 # 2017.12.20 10:47:28 CST # 2017.12.20 11:29:30 CST import cv2 import numpy as np ##(1) read into bgr-space img = cv2.imread("test2.jpg") ##(2) convert to hsv-space, then split the channels hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) h,s,v = cv2.split(hsv) ##(3) threshold the S channel using adaptive method(`THRESH_OTSU`) or fixed thresh th, threshed = cv2.threshold(s, 50, 255, cv2.THRESH_BINARY_INV) ##(4) find all the external contours on the threshed S cnts = cv2.findContours(threshed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] canvas = img.copy() #cv2.drawContours(canvas, cnts, -1, (0,255,0), 1) ## sort and choose the largest contour cnts = sorted(cnts, key = cv2.contourArea) cnt = cnts[-1] ## approx the contour, so the get the corner points arclen = cv2.arcLength(cnt, True) approx = cv2.approxPolyDP(cnt, 0.02* arclen, True) cv2.drawContours(canvas, [cnt], -1, (255,0,0), 1, cv2.LINE_AA) cv2.drawContours(canvas, [approx], -1, (0, 0, 255), 1, cv2.LINE_AA) ## Ok, you can see the result as tag(6) cv2.imwrite("detected.png", canvas)
这篇关于使用 OpenCV 对彩色背景进行边缘检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!