Python file write all the bounding box coordinates using OpenCV

Question:

My task:
My task is to extract bounding box coordinates of following image:
enter image description here

I have following code. I am trying to get these coordinates using roi, but I am not sure how to get them.

import cv2
import numpy as np

large = cv2.imread('1.jpg')

small = cv2.cvtColor(large, cv2.COLOR_BGR2GRAY)

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
grad = cv2.morphologyEx(small, cv2.MORPH_GRADIENT, kernel)

_, bw = cv2.threshold(grad, 0.0, 255.0, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 1))
connected = cv2.morphologyEx(bw, cv2.MORPH_CLOSE, kernel)

contours, hierarchy = cv2.findContours(connected.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

mask = np.zeros(bw.shape, dtype=np.uint8)

for idx in range(len(contours)):
    x, y, w, h = cv2.boundingRect(contours[idx])
    mask[y:y+h, x:x+w] = 0
    cv2.drawContours(mask, contours, idx, (255, 255, 255), -1)
    r = float(cv2.countNonZero(mask[y:y+h, x:x+w])) / (w * h)

    if r > 0.45 and w > 8 and h > 8:
        cv2.rectangle(large, (x, y), (x+w-1, y+h-1), (0, 255, 0), 1)
        roi=large[y:y+h, x:x+w]

print(roi)

Result should be something like this:

1675,1335,2338,1338,2337,1455,1674,1452.  :Box1
3067,519,3604,521,3603,651,3066,648       :Box2
1017,721,1729,726,1728,857,1016,852       :Box3

I have referred:
Extract all bounding boxes using OpenCV Python . On this link they are extracting images inside bounding boxes when they already have annotated image with rectangular GUI as a input. I want to extract the detected regions into a text file. How do I do it?

Asked By: Ajinkya

||

Answers:

x, y, w, h = cv2.boundingRect(contours[idx]) is the coordinates you want, then write it to a txt file:

...
with open("coords.txt","w+") as file:
    for idx in range(len(contours)):
        x, y, w, h = cv2.boundingRect(contours[idx])
        mask[y:y+h, x:x+w] = 0
        file.write("Box {0}: ({1},{2}), ({3},{4}), ({5},{6}), ({7},{8})".format(idx,x,y,x+w,y,x+w,y+h,x,y+h))
        cv2.drawContours(mask, contours, idx, (255, 255, 255), -1)
        r = float(cv2.countNonZero(mask[y:y+h, x:x+w])) / (w * h)
...

The result will contain 4 points for each box, like this.

Box 0: (360,259), (364,259), (364,261), (360,261)
Box 1: (380,258), (385,258), (385,262), (380,262)
Box 2: (365,258), (370,258), (370,262), (365,262)
Box 3: (386,256), (393,256), (393,260), (386,260)
Box 4: (358,256), (361,256), (361,258), (358,258)
Answered By: Ha Bom
import cv2
import numpy as np

# Load an image in grayscale
img = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)

# Perform OTSU thresholding
thresh, img_bin = cv2.threshold(img, 128, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

# Find contours
contours, _ = cv2.findContours(img_bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# Iterate through all contours
for cnt in contours:
    # Get bounding box coordinates
    x, y, w, h = cv2.boundingRect(cnt)

    # Draw bounding box on the original image
    cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)

# Show the original image with bounding boxes
cv2.imshow("Bounding Boxes", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Answered By: Deepak Mistry