Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to extract bottom part from engineering drawing image using python?

Tags:

My input image

My input image

To extract highlighted part

To extract highlighted part

My desired output

My desired output

Please someone help and give me a suggestion. My images looks like this. This is just sample one. I need to crop the bottom template part and do OCR. I have attached my desire output picture. Please have a look. How to implement it using python?

PS: The sheet size will differ and there may the chance of template to dislocate. but mostly it will be in lower left corner

like image 691
BALAJI Avatar asked Dec 06 '19 12:12

BALAJI


1 Answers

Here's a potential approach:

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

  2. Fill in potential contours. We iterate through contours and filter using contour approximation to determine if they are rectangular.

  3. Perform morphological operations. We morph open to remove non-rectangular contours using a rectangular kernel.

  4. Filter and extract desired contour. Find contours and filter using contour approximation, aspect ratio, and contour area to isolate the desired contour. Then extract using Numpy slicing.


  1. Binary image

enter image description here

  1. Filled in contours

enter image description here

  1. Morphological operation to remove non-rectangular contours

enter image description here

  1. Desired contour highlighted in green

enter image description here

Extracted ROI

enter image description here

Code

import cv2

# Grayscale, blur, and threshold
image = cv2.imread('1.png')
original = image.copy()
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]

# Fill in potential contours
cnts = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.05 * peri, True)
    if len(approx) == 4:
        cv2.drawContours(thresh, [c], -1, (255,255,255), -1)

# Remove non rectangular contours
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (40,10))
close = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)

# Filtered for desired contour
cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.05 * peri, True)
    x,y,w,h = cv2.boundingRect(approx)
    aspect_ratio = w / float(h)
    area = cv2.contourArea(approx)
    if len(approx) == 4 and w > h and aspect_ratio > 2.75 and area > 45000:
        cv2.drawContours(image, [c], -1, (36,255,12), -1)
        ROI = original[y:y+h, x:x+w]

cv2.imwrite('image.png', image)
cv2.imwrite('ROI.png', ROI)
cv2.waitKey()
like image 131
nathancy Avatar answered Oct 02 '22 16:10

nathancy