opencv可以在同一篇论文中检测出两个不同大小的矩形中的一个
Opencv can detect one out of two different size rectangles in the same paper
我是 OpenCV 的新手,我正在 Java 中创建 OMR(光学标记识别)系统以检测多项选择题上的答案 sheet.I 已经创建了一个表格由一个大矩形组成,用于通过绘制正确的圆来回答问题,以及一个用于检测唯一数字的小矩形,该数字是回答者的身份。
这是表格的图片:
现在我的程序正在检测 AM 的上方矩形,但无法检测到较大的矩形。我的图像正在通过 6 个阶段,第 1 个膨胀、第 2 个灰色、第 3 个阈值、第 4 个模糊、第 5 个精明和第 6 个自适应阈值。在这里你可以看到
dilated1 = new Mat(source1.size(), CV_8UC1);
dilate(source1, dilated1, getStructuringElement(MORPH_RECT, new Size(3, 3)));
gray1 = new Mat(dilated1.size(), CV_8UC1);
cvtColor(dilated1, gray1, COLOR_BGR2GRAY);
thresh1 = new Mat(gray1.rows(), gray1.cols(), gray1.type());
threshold(gray1, thresh1, 0, 255, THRESH_BINARY + THRESH_OTSU );
blur1 = new Mat(thresh1.size(), CV_8UC1);
blur(gray1, blur1, new Size(5.,5.));
canny1 = new Mat(blur1.size(), CV_8UC1);
Canny(blur1, canny1,160, 80);
adaptiveThresh1 = new Mat(canny1.rows(), gray1.cols(), gray1.type());
adaptiveThreshold(canny1, adaptiveThresh1, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 11,2);
我也在用这样的 findContours
findContours(adaptiveThresh1.clone(), contours1, hierarchy1, RETR_TREE, CHAIN_APPROX_SIMPLE);
我创建了两个不同的 java 类 因为在小矩形和大矩形中还有其他要检测的东西。上面的代码是我用来尝试检测更大矩形的代码。我在所有步骤中尝试了很多不同的数字,但仍然没有。
当我只使用图像中较大的矩形时,它工作得很好,但与另一个矩形结合使用时,它无法检测到它。这是我的论文,对我来说真的很重要。感谢任何帮助,如果您希望我添加任何内容以帮助您,请告诉我。
您可以找到最大 等高线和第二大 等高线。
建议阶段:
- 将图像转换为灰度(就像您所做的那样)。
- 在图像周围绘制白色粗矩形 - 确保图像周围没有黑色轮廓。
- 应用阈值并转换为二进制(就像您所做的那样)。
我发布的代码也是反极性的,因为轮廓是白色的。
- 寻找轮廓。
使用 RETR_EXTERNAL
而不是 RETR_TREE
,因为您不需要在等高线中找到等高线。
- 遍历等高线,找出面积最大的一张,面积第二大的一张。
面积最大的轮廓是下面的矩形。
面积第二大的等高线是上面的矩形。
这是一个 Python 实现(不是 JAVA,但足够接近):
import cv2
# Read input image
img = cv2.imread('image.png')
# Draw thick rectangle around the image - making sure there is not black contour around the image
cv2.rectangle(img, (0, 0), (img.shape[1], img.shape[0]), (255, 255, 255), thickness = 5)
# Convert from BGR to Grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Apply threshold on gray image - use automatic threshold algorithm (use THRESH_OTSU) and invert polarity.
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
# Find contours
cnts, heir = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
max_a = 0 # Maximum area
smax_a = 0 # Second maximum area
max_c = [] # Contour with maximum area
smax_c = [] # Contour with second maximum area (maximum excluding max_c)
# Iterate contours
for c in cnts:
area = cv2.contourArea(c)
if area > max_a: # If area is grater than maximum, second max = max, and max = area
smax_a = max_a
smax_c = max_c # Second max contour gets maximum contour
max_a = area
max_c = c # Maximum contour gets c
elif area > smax_a: # If area is grater than second maximum, replace second maximum
smax_a = area
smax_c = c
#Get bounding rectangle of contour with maximum area, and mark it with green rectangle
x, y, w, h = cv2.boundingRect(max_c)
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), thickness = 2)
#Get bounding rectangle of contour with second maximum area, and mark it with blue rectangle
x, y, w, h = cv2.boundingRect(smax_c)
cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), thickness = 2)
# Show result (for testing).
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果:
我是 OpenCV 的新手,我正在 Java 中创建 OMR(光学标记识别)系统以检测多项选择题上的答案 sheet.I 已经创建了一个表格由一个大矩形组成,用于通过绘制正确的圆来回答问题,以及一个用于检测唯一数字的小矩形,该数字是回答者的身份。
这是表格的图片:
现在我的程序正在检测 AM 的上方矩形,但无法检测到较大的矩形。我的图像正在通过 6 个阶段,第 1 个膨胀、第 2 个灰色、第 3 个阈值、第 4 个模糊、第 5 个精明和第 6 个自适应阈值。在这里你可以看到
dilated1 = new Mat(source1.size(), CV_8UC1);
dilate(source1, dilated1, getStructuringElement(MORPH_RECT, new Size(3, 3)));
gray1 = new Mat(dilated1.size(), CV_8UC1);
cvtColor(dilated1, gray1, COLOR_BGR2GRAY);
thresh1 = new Mat(gray1.rows(), gray1.cols(), gray1.type());
threshold(gray1, thresh1, 0, 255, THRESH_BINARY + THRESH_OTSU );
blur1 = new Mat(thresh1.size(), CV_8UC1);
blur(gray1, blur1, new Size(5.,5.));
canny1 = new Mat(blur1.size(), CV_8UC1);
Canny(blur1, canny1,160, 80);
adaptiveThresh1 = new Mat(canny1.rows(), gray1.cols(), gray1.type());
adaptiveThreshold(canny1, adaptiveThresh1, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 11,2);
我也在用这样的 findContours
findContours(adaptiveThresh1.clone(), contours1, hierarchy1, RETR_TREE, CHAIN_APPROX_SIMPLE);
我创建了两个不同的 java 类 因为在小矩形和大矩形中还有其他要检测的东西。上面的代码是我用来尝试检测更大矩形的代码。我在所有步骤中尝试了很多不同的数字,但仍然没有。
当我只使用图像中较大的矩形时,它工作得很好,但与另一个矩形结合使用时,它无法检测到它。这是我的论文,对我来说真的很重要。感谢任何帮助,如果您希望我添加任何内容以帮助您,请告诉我。
您可以找到最大 等高线和第二大 等高线。
建议阶段:
- 将图像转换为灰度(就像您所做的那样)。
- 在图像周围绘制白色粗矩形 - 确保图像周围没有黑色轮廓。
- 应用阈值并转换为二进制(就像您所做的那样)。
我发布的代码也是反极性的,因为轮廓是白色的。 - 寻找轮廓。
使用RETR_EXTERNAL
而不是RETR_TREE
,因为您不需要在等高线中找到等高线。 - 遍历等高线,找出面积最大的一张,面积第二大的一张。
面积最大的轮廓是下面的矩形。
面积第二大的等高线是上面的矩形。
这是一个 Python 实现(不是 JAVA,但足够接近):
import cv2
# Read input image
img = cv2.imread('image.png')
# Draw thick rectangle around the image - making sure there is not black contour around the image
cv2.rectangle(img, (0, 0), (img.shape[1], img.shape[0]), (255, 255, 255), thickness = 5)
# Convert from BGR to Grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Apply threshold on gray image - use automatic threshold algorithm (use THRESH_OTSU) and invert polarity.
ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
# Find contours
cnts, heir = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
max_a = 0 # Maximum area
smax_a = 0 # Second maximum area
max_c = [] # Contour with maximum area
smax_c = [] # Contour with second maximum area (maximum excluding max_c)
# Iterate contours
for c in cnts:
area = cv2.contourArea(c)
if area > max_a: # If area is grater than maximum, second max = max, and max = area
smax_a = max_a
smax_c = max_c # Second max contour gets maximum contour
max_a = area
max_c = c # Maximum contour gets c
elif area > smax_a: # If area is grater than second maximum, replace second maximum
smax_a = area
smax_c = c
#Get bounding rectangle of contour with maximum area, and mark it with green rectangle
x, y, w, h = cv2.boundingRect(max_c)
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), thickness = 2)
#Get bounding rectangle of contour with second maximum area, and mark it with blue rectangle
x, y, w, h = cv2.boundingRect(smax_c)
cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), thickness = 2)
# Show result (for testing).
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果: