OpenCV Contours. having trouble finding the desired contour of a given image

Question:

[][1]

This is the image I need to do contour detection on. I need to contour the characters inside and outside the rectangle, but not the rectangle itself. The Second image I attached is the desired output.

enter image description here

Now this is the approach I have tried so far:

import cv2

# Read the image
image = cv2.imread('fig1.jpg')

# Convert the image to grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# Apply histogram equalization to enhance contrast
equalized = cv2.equalizeHist(gray)

# Apply Gaussian blur to the equalized image
blurred = cv2.GaussianBlur(equalized, (5, 5), 0)

# Apply Laplacian operator to detect edges
edges = cv2.Laplacian(blurred, cv2.CV_64F)

# Apply thresholding to create a binary image
_, edges_binary = cv2.threshold(edges, 20, 255, cv2.THRESH_BINARY)

# Convert edges_binary to the appropriate data type (CV_8UC1)
edges_binary = edges_binary.astype(np.uint8)

# Find contours of the edges
contours, _ = cv2.findContours(edges_binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# Draw the sides of the rectangle (for visualization)
cv2.drawContours(image, contours, -1, (255, 255, 255), 2)

# Get the bounding box of the rectangle
x, y, w, h = cv2.boundingRect(contours[0])

# Omit the sides of the rectangle from the binary image
edges_binary[y:y+h, x:x+w] = 0
# Find contours in the modified binary image
contours, _ = cv2.findContours(edges_binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Draw contours on the original image
cv2.drawContours(image, contours, -1, (0, 255, 0), 2)

# Display the result
cv2.imshow('Contour Detection', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

enter image description here

I feel as though I am very close. I have tried several other approaches, but this one creates the closest to the desired result. I only learned OpenCV Last week, so can anyone tell me what else I can try?

Answers:

You can use the contour area to avoid the large outer rectangle. Try the below code. Final result will have the bounding boxes of letters and symbols. Hope this helps.

import cv2
import numpy as np

#READ IMAGE AND APPLY THRESHOLD
image = cv2.imread("letters.jpg")
grayscale_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ret, thresholded_image = cv2.threshold(grayscale_image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

#FIND THE CONTOURS IN IMAGE
contours, hierarchy = cv2.findContours(thresholded_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contour_image = np.zeros_like(thresholded_image)

#SELECT CONTOURS WHICH ARE SMALL, LESS AREA COMPARED TO LARGE RECTANGLE
selected_ctr =[]
selected_bounding_rect = []
for ctr in contours:
    if cv2.contourArea(ctr) < 1000: #ADJUST THIS ACCORDING TO YOUR NEED.
        selected_ctr.append(ctr) #SELECT CONTOUR
        selected_bounding_rect.append(cv2.boundingRect(ctr)) #GET BOUNDING BOX

#DRAW CONTOURS OF THE FOUND LETTERS AND SYMBOLS
cv2.drawContours(contour_image, selected_ctr, -1, 255, thickness=1)
cv2.imwrite("letters_ctr.jpg",contour_image) # SAVE CONTOUR IMAGE

#DRAW THE SELECTED  RECTANGLES
for rect in selected_bounding_rect:
    image_rect = cv2.rectangle(image, rect,  (0, 255, 0) , 1)
cv2.imwrite("letters_rect.jpg",image_rect) #SAVE RECTANGLE DRAWN IMAGE

Output:

enter image description here

Answered By: KRG
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.