Обнаружение нескольких родительских (и дочерних) контуров с помощью openCVPython

Программы на Python
Ответить
Anonymous
 Обнаружение нескольких родительских (и дочерних) контуров с помощью openCV

Сообщение Anonymous »

Я работаю над скриптом Python, который обрабатывает изображения с помощью OpenCV для обнаружения контуров и классификации их на родительские и дочерние контуры. Скрипт генерирует:
  • Размеченную визуализацию контуров (синие рамки для родителей,
    зеленые рамки для детей).
  • CSV-файл, содержащий метрики об иерархии
    контуров.
Проблема: скрипт не может правильно обнаружить и пометить несколько родительских элементов. контуры. Он идентифицирует только один родительский контур (неправильно классифицирован) и неправильно маркирует остальные.
Ожидаемый результат:
  • Изображение должно отобразиться :
  • 4 родительских контура (синие рамки).
  • Первые 3 родительских элемента должно иметь по 4 дочерних контура каждый (зеленые
    рамки).
  • Последний родительский элемент (треугольник) не должен иметь дочерних элементов.
  • Вывод показателей (пример с фиктивными данными):
< thead>

Ярлык
Родительский ярлык
Ширина
Высота
Площадь




parent_1
parent_1
2480
3508
8693853.0


contour_1
parent_1710
452
161933.0


contour_2
parent_1
1251
1062
795647.0


contour_3
parent_1
709
1324
736735.0

contour_4
parent_1
869
943
812353.0


parent_2
parent_22480
3508
8693853.0


contour_1
parent_2
710
452
161933.0


contour_2
parent_2
1251
1062
795647.0

contour_3
parent_2
709
1324
736735.0


contour_4
parent_2869
943
812353.0


parent_3
parent_3
2480
3508
8693853.0


contour_1
parent_3
710
452
161933.0

contour_2
parent_3
1251
1062
795647.0


contour_3
parent_3709
1324
736735.0


contour_4
parent_3
869
943
812353.0


parent_4
parent_4
869
943
812353.0



Вот скрипт:

Код: Выделить всё

import cv2
import numpy as np
import pandas as pd
import os

def process_image_with_multiple_parents(image_path, output_dir):
# Load image
image = cv2.imread(image_path)
if image is None:
print(f"Error: Unable to load image from {image_path}")
return

# Grayscale
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# Thresholding
_, thresholded_image = cv2.threshold(gray_image, 127, 255, cv2.THRESH_BINARY)

# Find parent and child contours
contours, hierarchy = cv2.findContours(thresholded_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
if hierarchy is not None:
hierarchy = hierarchy[0]  # Flatten the hierarchy array

# Store metrics
metrics = []
image_height, image_width = thresholded_image.shape[:2]

# Create a labeled visualization
labeled_image = cv2.cvtColor(thresholded_image, cv2.COLOR_GRAY2BGR)

parent_count = 0
for idx, (contour, h) in enumerate(zip(contours, hierarchy)):
# Identify top-level contours (parents)
if h[3] == -1:  # No parent
parent_count += 1
parent_label = f"parent_{parent_count}"

# Draw parent contour
cv2.drawContours(labeled_image, [contour], -1, (255, 0, 0), 2)  # Blue for parent
cx, cy = tuple(np.mean(contour, axis=0).astype(int)[0])  # Centroid of parent
cv2.putText(labeled_image, parent_label, (cx - 20, cy), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 1)

# Save metrics for the parent contour
x, y, width, height = cv2.boundingRect(contour)
parent_area = cv2.contourArea(contour)
metrics.append({
"label": parent_label,
"parent_label":  parent_label,  # Parent references itself
"width": width,
"height": height,
"area": parent_area
})

# child contours
child_count = 0
for child_idx, (child_contour, child_h) in enumerate(zip(contours, hierarchy)):
if child_h[3] == idx:  # Child of the current parent
child_count += 1
child_label = f"contour_{child_count}"

# Save metrics for the child contours
x, y, width, height = cv2.boundingRect(child_contour)
area = cv2.contourArea(child_contour)
metrics.append({
"label": child_label,
"parent_label": parent_label,
"width": width,
"height": height,
"area": area
})

# Draw the child contours
cv2.drawContours(labeled_image, [child_contour], -1, (0, 255, 0), 5)  # Green for child
cx, cy = tuple(np.mean(child_contour, axis=0).astype(int)[0])  # Centroid of child
cv2.putText(labeled_image, child_label, (cx - 20, cy), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 1)

# Save the labeled visualization
os.makedirs(output_dir, exist_ok=True)
labeled_image_path = os.path.join(output_dir, "labeled_image.png")
cv2.imwrite(labeled_image_path, labeled_image)
print(f"Labeled image saved to: {labeled_image_path}")

# Save the parent/child metrics to a CSV file
metrics_df = pd.DataFrame(metrics)
csv_path = os.path.join(output_dir, "contour_metrics.csv")
metrics_df.to_csv(csv_path, index=False)
print(f"Metrics saved to: {csv_path}")

# Run it
if __name__ == "__main__":
image_path = "test_image.png"  # image path
output_dir = "output"
process_image_with_multiple_parents(image_path, output_dir)

Изображение

< img alt="текущий вывод" src="https://i.sstatic.net/GPYFvMoQ.png" />

Подробнее здесь: https://stackoverflow.com/questions/792 ... ith-opencv
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»