useruser123
useruser123

Reputation: 89

find rectangle in image and extract text inside of it to save it as new image

I am new to OpenCV so I really need your help. I have a bunch of images like this one:

enter image description here

I need to detect the rectangle on the image, extract the text part from it and save it as a new image.

Can you please help me with this?

Thank you!

Upvotes: 1

Views: 5239

Answers (2)

kavko
kavko

Reputation: 2831

Just to add to Danyals answer I have added an example code with steps written in comments. For this image you don't even need to perform morphological opening on the image. But usually for this kind of noise in the image it is recomended. Cheers!

import cv2
import numpy as np

# Read the image and create a blank mask
img = cv2.imread('napis.jpg')
h,w = img.shape[:2]
mask = np.zeros((h,w), np.uint8)

# Transform to gray colorspace and invert Otsu threshold the image
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

# ***OPTIONAL FOR THIS IMAGE

### Perform opening (erosion followed by dilation)
#kernel = np.ones((2,2),np.uint8)
#opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)

# ***

# Search for contours, select the biggest and draw it on the mask
_, contours, hierarchy = cv2.findContours(thresh, # if you use opening then change "thresh" to "opening"
                                          cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)
cv2.drawContours(mask, [cnt], 0, 255, -1)

# Perform a bitwise operation
res = cv2.bitwise_and(img, img, mask=mask)

########### The result is a ROI with some noise
########### Clearing the noise

# Create a new mask
mask = np.zeros((h,w), np.uint8)

# Transform the resulting image to gray colorspace and Otsu threshold the image 
gray = cv2.cvtColor(res,cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# Search for contours and select the biggest one again
_, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)

# Draw it on the new mask and perform a bitwise operation again
cv2.drawContours(mask, [cnt], 0, 255, -1)
res = cv2.bitwise_and(img, img, mask=mask)

# If you will use pytesseract it is wise to make an aditional white border
# so that the letters arent on the borders
x,y,w,h = cv2.boundingRect(cnt)
cv2.rectangle(res,(x,y),(x+w,y+h),(255,255,255),1)

# Crop the result
final_image = res[y:y+h+1, x:x+w+1]

# Display the result
cv2.imshow('img', final_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

Result:

enter image description here

Upvotes: 3

Danyal
Danyal

Reputation: 533

One way to do this (if the rectangle sizes are somewhat predictable) is:

  1. Convert the image to black and white
  2. Invert the image
  3. Perform morphological opening on the image from (2) with a horizontal line / rectangle (I tried with 2x30).
  4. Perform morphological opening on the image from (2) with a vertical line (I tried it with 15x2).
  5. Add the images from (3) and (4). You should only have a white rectangle now. Now can remove all corresponding rows and columns in the original image that are entirely zero in this image.

Upvotes: 2

Related Questions