1

I'm trying to find grid elements with circle/cross or something filled inside it. I used code from here to build my logic.

Logic - Find grid coorindates -> Extract subimage of grid element using top-left and bottom-right coorindates of each rectangle block -> Find # of non-zero pixels -> If rectangle is more than 50% filled take it as filled

If grid is empty I am able to find all grid coordinates successfully. However, if any grid element is filled things do not work as expected as you can see from images. How can I fix this code to determine all grid coorindates successfully every time?

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)
Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
user1146904
  • 243
  • 2
  • 6
  • 13

1 Answers1

0

Use hough transform for line detection OpenCV Hough Transform; it will be robust to occlusions and illumination changes . Perhaps you can also assume that horizontal and vertical lines are equidistantial, so you need to detect only two lines for horizontal and two for vertical orientation.

Blaz Bratanic
  • 2,279
  • 12
  • 17