Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Square detection in image

I am trying to detect all the squared shaped dice images so that i can crop them individually and use that for OCR. Below is the Original image:

image3 image4

Here is the code i have got but it is missing some squares.

def find_squares(img):
    img = cv2.GaussianBlur(img, (5, 5), 0)
    squares = []
    for gray in cv2.split(img):
        for thrs in range(0, 255, 26):
            if thrs == 0:
                bin = cv2.Canny(gray, 0, 50, apertureSize=5)
                bin = cv2.dilate(bin, None)
            else:
                _retval, bin = cv2.threshold(gray, thrs, 255, cv2.THRESH_BINARY)
            bin, contours, _hierarchy = cv2.findContours(bin, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
            for cnt in contours:
                cnt_len = cv2.arcLength(cnt, True)
                cnt = cv2.approxPolyDP(cnt, 0.02*cnt_len, True)
                if len(cnt) == 4 and cv2.contourArea(cnt) > 1000 and cv2.isContourConvex(cnt):
                    cnt = cnt.reshape(-1, 2)
                    max_cos = np.max([angle_cos( cnt[i], cnt[(i+1) % 4], cnt[(i+2) % 4] ) for i in range(4)])
                    #print(cnt)
                    a = (cnt[1][1] - cnt[0][1])

                    if max_cos < 0.1 and a < img.shape[0]*0.8:

                        squares.append(cnt)
    return squares

dice = cv2.imread('img1.png')
squares = find_squares(dice)
cv2.drawContours(dice, squares, -1, (0, 255, 0), 3)

Here are the Output images: Image1Image2

As per my analysis, some squares are missing due to missing canny edges along the dice because of smooth intensity transition between dice and background.

Given the constraint that there will always be 25 dices in square grid pattern (5*5) can we predict the missing square positions based on recognised squares? Or can we modify above algorithm for square detection algorithm?

like image 869
flamelite Avatar asked Mar 14 '19 18:03

flamelite


People also ask

How do you identify a square in a picture?

Detect and extract squares.Sharpen image with cv2. filter2D() using a generic sharpening kernel, other kernels can be found here. Next find contours and filter using cv2. contourArea() with minimum/maximum threshold values.

What is shape detection?

Shape detection is an important part of Image Processing referring to modules that deal with identifying and detecting shapes of parts of image which differ in brightness,color or texture.

How do you find a rectangle in a picture?

Use the findContours() and contourArea() Function of OpenCV to Detect Rectangles in Images in Python. We can detect a rectangle present in an image using the findContours() function of OpenCV, and we can use the contourArea() function to sort different rectangles according to their area.

What is image contour detection?

Contour Detection in an Image (C#) Contours detection is a process can be explained simply as a curve joining all the continuous points (along with the boundary), having same colour or intensity. The contours are a useful tool for shape analysis and object detection and recognition.


1 Answers

Here's an approach

  • Convert image to grayscale and median blur to smooth image
  • Sharpen image to enhance edges
  • Threshold. Depending on the image, Otsu's thresholding or Adaptive thresholding would work
  • Perform morphological transformations
  • Find contours and filter using minimum/maximum threshold area
  • Crop and save ROI

Sharpen image with cv2.filter2D(). We use a generic sharpen kernel, other kernels can be found here

enter image description here

Now threshold to get a binary image

enter image description here

Perform morphological operations

enter image description here

From here we find contours and filter using cv2.contourArea() with minimum/maximum threshold areas.

enter image description here

We can crop each desired square region using Numpy slicing and save each ROI like this

x,y,w,h = cv2.boundingRect(c)
ROI = image[y:y+h, x:x+w]
cv2.imwrite('ROI_{}.png'.format(image_number), ROI)

enter image description here

import cv2
import numpy as np

image = cv2.imread('1.png')

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.medianBlur(gray, 5)
sharpen_kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
sharpen = cv2.filter2D(blur, -1, sharpen_kernel)

thresh = cv2.threshold(sharpen,160,255, cv2.THRESH_BINARY_INV)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
close = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=2)

cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

min_area = 100
max_area = 1500
image_number = 0
for c in cnts:
    area = cv2.contourArea(c)
    if area > min_area and area < max_area:
        x,y,w,h = cv2.boundingRect(c)
        ROI = image[y:y+h, x:x+w]
        cv2.imwrite('ROI_{}.png'.format(image_number), ROI)
        cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 2)
        image_number += 1

cv2.imshow('sharpen', sharpen)
cv2.imshow('close', close)
cv2.imshow('thresh', thresh)
cv2.imshow('image', image)
cv2.waitKey()
like image 154
nathancy Avatar answered Oct 19 '22 06:10

nathancy