Home > Mobile >  Find circle objects (stamps) without clear contours in document image Python OpenCV
Find circle objects (stamps) without clear contours in document image Python OpenCV

Time:03-22

I wrote a simple code to search for circles in documents (since seals have a rounded shape).

But due to the poor image quality, the print outline is fuzzy, and opencv cannot always detect it. I edited the picture in photoshop and enhanced the dark colors. I saved the picture and sent it for processing. It helped me. Opencv has identified a circle representing a low-quality print (there are no such problems in high-quality documents). My code:

import numpy as np
import cv2

img = cv2.imread(r"C:\buh\doc.jpg")

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)


# I tried experimenting with bluer, but opencv doesn't see circles in this case
# blurred = cv2.bilateralFilter(gray.copy(), 15, 15, 15 )
# imS = cv2.resize(blurred, (960, 540))
# cv2.imshow('img', imS)
# cv2.waitKey(0)



minDist = 100
param1 = 30 #500
param2 = 100 #200 #smaller value-> more false circles
minRadius = 90
maxRadius = 200 #10

# docstring of HoughCircles: HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) -> circles
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, minDist, param1=param1, param2=param2, minRadius=minRadius, maxRadius=maxRadius)

if circles is not None:
    circles = np.uint16(np.around(circles))
    for i in circles[0, :]:
        cv2.circle(img, (i[0], i[1]), i[2], (0, 255, 0), 2)

# Show result for testing:
imS = cv2.resize(img, (960, 540))
cv2.imshow('img', imS)
cv2.waitKey(0)

The seals in the documents are circles as in the photo:

enter image description here

Unfortunately, I cannot add photo of the document where the original seals are located, since this is a private information...

So, I need to enhance the shades of black in the photo before trying to look for circles. How can I do this? I would also listen to other suggestions for improving the contours of seals (stamps), if someone has already encountered this.

Thank you.

Example:

enter image description here

CodePudding user response:

Here's a simple approach:

  1. Obtain binary image. Load image, convert to grayscale, Gaussian blur, then Otsu's threshold.

  2. Merge small contours into a single large contour. We dilate using cv2.dilate to merge circles into a single contour.

  3. Find external contours. Finally we find external contours with the external cv2.RETR_EXTERNAL flag and cv2.drawContours()


Visualization of the image pipeline

Input image

Threshold for binary image

Dilate

Detected contours in green

Code

import cv2
import numpy as np

# Load image, grayscale, Gaussian blur, Otsus threshold, dilate
image = cv2.imread('3.PNG')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (3,3), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV   cv2.THRESH_OTSU)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
dilate = cv2.dilate(thresh, kernel, iterations=1)

# Find contours
cnts = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(image, [c], -1, (36,255,12), 3)

cv2.imshow('image', image)
cv2.imshow('dilate', dilate)
cv2.imshow('thresh', thresh)
cv2.waitKey()     
  • Related