2

I have an image similar to the following. I want to separate two numbers 7 and 4 as shown in the image, in that I want to have a bounding box for each of these two objects.

enter image description here

How could I do this with OpenCV? I have no idea, how could I do this and was thinking if there is some way by using Sobel operator. The only thing that I tired was getting the Sobel.

s = cv2.Sobel(img, cv2.CV_64F,1,0,ksize=5)

enter image description here

but have no idea on how to proceed from here.

nathancy
  • 42,661
  • 14
  • 115
  • 137
Amanda
  • 2,013
  • 3
  • 24
  • 57
  • Possible duplicate of [How to Segment handwritten and printed digit without losing information in opencv?](https://stackoverflow.com/questions/52995607/how-to-segment-handwritten-and-printed-digit-without-losing-information-in-openc) – Shubhankar Mohan Apr 21 '19 at 14:58

2 Answers2

5

To segment and detect figures in an image, the main idea is as follows:

  1. Convert image into grayscale using cv2.cvtColor()
  2. Blur image with cv2.GaussianBlur()
  3. Find edges with cv2.Canny()
  4. Find contours with cv2.findContours() and sort from left-to-right using imutils.contours.sort_contours() to ensure that when we iterate through contours, they are in the correct order
  5. Iterate through each contour
    • Obtain bounding rectangle using cv2.boundingRect()
    • Find ROI of each contour with Numpy slicing
    • Draw bounding box rectangle using cv2.rectangle()

Canny Edge Detection

enter image description here

Detected Contours

enter image description here

Cropped and saved ROIs

enter image description here

Output

Contours Detected: 2

Code

import numpy as np
import cv2
from imutils import contours

# Load image, grayscale, Gaussian blur, Canny edge detection
image = cv2.imread("1.png")
original = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (3,3), 0)
canny = cv2.Canny(blurred, 120, 255, 1)

# Find contours and extract ROI
ROI_number = 0
cnts = cv2.findContours(canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts, _ = contours.sort_contours(cnts, method="left-to-right")
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    ROI = original[y:y+h, x:x+w]
    cv2.rectangle(image, (x,y), (x+w,y+h),(36, 255, 12), 3)
    cv2.imwrite('ROI_{}.png'.format(ROI_number), ROI)
    ROI_number += 1

print('Contours Detected: {}'.format(ROI_number))
cv2.imshow("image", image) 
cv2.imshow("canny", canny)
cv2.waitKey()
nathancy
  • 42,661
  • 14
  • 115
  • 137
1

Follow the steps:

  1. Convert the image into grayscale.
  2. Use thresholding to convert image into a binary image, in your problem I think adaptive gausian will be most beneficial to use.
  3. Apply contour detection and then you can make bounding box around contours.

You may need to filter contours based on size or position.

Community
  • 1
  • 1