找到填充的网格元素

时间:2014-04-11 05:32:18

标签: python opencv image-processing optical-mark-recognition

我正在尝试找到带有圆圈/十字架或其中填充的东西的网格元素。我使用here中的代码来构建我的逻辑。

逻辑 - 查找网格coorindates - >使用每个矩形块的左上角和右下角坐标提取网格元素的子图像 - >找到非零像素的数量 - >如果矩形填充超过50%,请将其填充为

如果网格为空,我可以成功找到所有网格坐标。但是,如果填充了任何网格元素,则事物无法正常工作,因为您可以从图像中看到。如何修复此代码以确保每次都成功确定所有网格coorindates?

image.png res2.png res3.png res4.png res5.png res6.png

import cv2
import cv
import numpy as np
import operator
from PIL import Image
import math


region = cv2.imread("image.png")
img = cv2.GaussianBlur(region,(5,5),0)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
mask = np.zeros((gray.shape),np.uint8)
kernel1 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(11,11))

close = cv2.morphologyEx(gray,cv2.MORPH_CLOSE,kernel1)
div = np.float32(gray)/(close)
res = np.uint8(cv2.normalize(div,div,0,255,cv2.NORM_MINMAX))
res2 = cv2.cvtColor(res,cv2.COLOR_GRAY2BGR)

##finding rectangles & creating mask image
thresh = cv2.adaptiveThreshold(res,255,0,1,19,2)
contour,hier = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

max_area = 0
best_cnt = None
for cnt in contour:
    area = cv2.contourArea(cnt)
    if area > 1000:
        if area > max_area:
            max_area = area
            best_cnt = cnt

cv2.drawContours(mask,[best_cnt],0,255,-1)
cv2.drawContours(mask,[best_cnt],0,0,2)

res = cv2.bitwise_and(res,mask)
cv2.imwrite("res2.png",res)

##Finding vertical lines
kernelx = cv2.getStructuringElement(cv2.MORPH_RECT,(2,10))

dx = cv2.Sobel(res,cv2.CV_16S,1,0)
dx = cv2.convertScaleAbs(dx)
cv2.normalize(dx,dx,0,255,cv2.NORM_MINMAX)
ret,close = cv2.threshold(dx,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
close = cv2.morphologyEx(close,cv2.MORPH_DILATE,kernelx,iterations = 1)

contour, hier = cv2.findContours(close,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
for cnt in contour:
    x,y,w,h = cv2.boundingRect(cnt)
    if h/w > 5:
        cv2.drawContours(close,[cnt],0,255,-1)
    else:
        cv2.drawContours(close,[cnt],0,0,-1)
close = cv2.morphologyEx(close,cv2.MORPH_CLOSE,None,iterations = 2)
closex = close.copy()
cv2.imwrite("res3.png",closex)

##Finding horizontal lines
kernely = cv2.getStructuringElement(cv2.MORPH_RECT,(10,2))
dy = cv2.Sobel(res,cv2.CV_16S,0,2)
dy = cv2.convertScaleAbs(dy)
cv2.normalize(dy,dy,0,255,cv2.NORM_MINMAX)
ret,close = cv2.threshold(dy,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
close = cv2.morphologyEx(close,cv2.MORPH_DILATE,kernely)

contour, hier = cv2.findContours(close,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
for cnt in contour:
    x,y,w,h = cv2.boundingRect(cnt)
    if w/h > 5:
        cv2.drawContours(close,[cnt],0,255,-1)
    else:
        cv2.drawContours(close,[cnt],0,0,-1)

close = cv2.morphologyEx(close,cv2.MORPH_DILATE,None,iterations = 2)
closey = close.copy()
cv2.imwrite("res4.png",closey)

##Finding grid points
res = cv2.bitwise_and(closex,closey)
cv2.imwrite("res5.png",res)

1 个答案:

答案 0 :(得分:0)

使用hough变换进行线检测OpenCV Hough Transform;它对遮挡和光照变化很有效。也许您也可以假设水平线和垂直线是等距的,因此您只需检测两条水平线和两条垂直线。