0

I have this image.Rectangles with lines. I have to assign the number (1 to 4) below the image of the rectangle with respect to its length inside the rectangle. The shorter the line lower the number. I am using OpenCV and Jupyter Notebook. How can I accomplish this?

I tried using Hough line transform and contour detection using OpenCV. But Hough line transform detects way too many lines even in places where there are no lines. This is my first time experimenting with images and OpenCV.

Also, I would be grateful if you could also tell me how to make the rectangles straight along with the straight lines inside them. Although I haven't tried doing this myself yet, it will be helpful.

Edit Based on the suggestion by @fmw42, I ended up doing the followig.

import cv2
import numpy as np
import matplotlib.pyplot as plt

# Load the image
image = cv2.imread('rects.png')

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150)

# Find contours in the edge-detected image with hierarchical retrieval
contours, hierarchy = cv2.findContours(edges, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)

# Create a copy of the original image to draw the contours on
contour_image = image.copy()

# Lists to store the lengths of inner contours (lines)
inner_contour_lengths = []

# Loop through the contours and hierarchy
for i, contour in enumerate(contours):
    # Get the parent index from the hierarchy
    parent_idx = hierarchy[0][i][3]
    
    if parent_idx != -1:
        # Inner contour, line
        perimeter = cv2.arcLength(contour, True)
        inner_contour_lengths.append((perimeter, i))  # Store length and index

# Sort the inner contour lengths in ascending order
inner_contour_lengths.sort()

# Assign numbers to the lines based on their lengths
line_numbers = {length_index[1]: i + 1 for i, length_index in enumerate(inner_contour_lengths)}

# Draw and label the lines for the four contours with lowest lengths
for length, index in inner_contour_lengths[:4]:  # Only the first four contours
    contour = contours[index]
    cv2.drawContours(contour_image, [contour], -1, (0, 255, 0), 2)  # Green color
    number = line_numbers[index]
    cv2.putText(contour_image, str(number), tuple(contour[0][0]), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)  # Red color

plt.imshow(cv2.cvtColor(contour_image, cv2.COLOR_BGR2RGB))
plt.show()

The result is here.result image. If there is a better way to do it, please tell me.

  • Get contours. Find the inner contour for the lines and measure its area or perimeter to determine the size (length) and sort on that. Then number your rectangle (outer contours). – fmw42 Aug 16 '23 at 16:44
  • Welcome to Stack Overflow. Please read the information guides in the **help center** (https://stackoverflow.com/help), in particular, "How to Ask A Good Question" (https://stackoverflow.com/help/how-to-ask) and "How to create a Minimal, Reproducible Example" (https://stackoverflow.com/help/minimal-reproducible-example). – fmw42 Aug 16 '23 at 16:45
  • Please provide enough code so others can better understand or reproduce the problem. – Community Aug 16 '23 at 17:06
  • not touching this question until you can assure us that the problem really is as simple as black rectangles containing single black lines. if the problem is not that simple, any suggested approaches would be shot down, hence being a waste of time. – Christoph Rackwitz Aug 17 '23 at 07:22

0 Answers0