Детектор прямоугольных коробок и рисование ограничивающих рамок

я пытаюсь обнаружить некоторые таблицы из изображения, но структура изображений затрудняет использование некоторых библиотек для их извлечения, поэтому я решил извлечь их как изображения, я попытался использовать приведенный ниже код для рисования ограничивающих рамок вокруг прямоугольников, код работает, но, похоже, не обнаруживает прямоугольники более светлых цветов:

это код, который я использую:

import numpy as np 
import cv2

#load the image
image = cv2.imread("aaaaaaaaaaa.jpg")

# grayscale
result = image.copy()
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)

# adaptive threshold
thresh = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,51,9)

# Fill rectangular contours
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(thresh, [c], -1, (255,255,255), -1)

# Morph open
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9,9))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=4)

# Draw rectangles, the 'area_treshold' value was determined empirically
cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
area_treshold = 4000
for c in cnts:
    if cv2.contourArea(c) > area_treshold :
      x,y,w,h = cv2.boundingRect(c)
      cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 3)

cv2.imwrite('thresh.jpg', thresh)
cv2.imwrite('opening.jpg', opening)
cv2.imwrite('image.jpg', image)
cv2.waitKey()

это ввод: это входное изображение

если вы заметили на изображении, оно обнаруживает только достаточно темные блоки, а не более светлые блокиэто результат

Любая помощь будет оценена

Привет, вы пытались заменить более светлые пиксели строк таблицы цветом с более высокой контрастностью (например, цветом строки заголовка)?

HansQ 30.03.2023 16:05

нет, не делал, как мне это сделать?

ovu sunday 30.03.2023 16:18

Прежде чем преобразовать изображение в оттенки серого с помощью линии gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY), вам нужно будет выяснить исходное значение цвета (например, просмотрев значения изображения в этой конкретной области). При этом вы можете просто сделать что-то вроде (image[is_my_color(image)] = target_color) с целевым цветом, представляющим собой массив значений BGR несколько более темного цвета np.array([b, g, r]).

HansQ 30.03.2023 16:24
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
3
132
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Мы можем increase_contrast предоставить cv2.findContours более подходящее изображение для работы:

def increase_contrast(x):
    return 127.0 if x >= 230.0 else 255.0

increase_contrast = np.vectorize(increase_contrast)
new_image = increase_contrast(gray)

Ответ принят как подходящий

Если вы знаете цвет таблицы, как насчет использования cv2.inRange() для порога изображения?

Вот пример с двумя разными диапазонами для отделения заголовка таблицы от тела.

import numpy as np 
import cv2

image = cv2.imread("image.jpg")
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

thresh_header = cv2.inRange(hsv, (10, 130, 0), (20, 140, 255))
thresh_body = cv2.inRange(hsv, (10, 80, 0), (20, 90, 255))

Теперь вы можете повторно использовать код, который вы сделали, чтобы найти контуры и нарисовать прямоугольники:

def draw_countours(image, thresh, color):
    cnts, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    for c in cnts:
        if cv2.contourArea(c) < area_treshold:
            continue
        x, y, w, h = cv2.boundingRect(c)
        cv2.rectangle(image, (x, y), (x + w, y + h), color, 3)
        
draw_countours(image, thresh_header, (0, 0, 255))
draw_countours(image, thresh_body, (255, 0, 0))

Вот пример результата

Обратите внимание, что, конечно, это работает только в том случае, если вы заранее знаете цвет стола.


РЕДАКТИРОВАТЬ из комментариев

есть ли способ извлечь или обрезать всю таблицу. это заголовки и тело в целом

В этом случае вы можете расширить диапазон HSV, используемый для порога изображения, чтобы получить заголовок и тело в одной маске (thresh_header + thresh_body).

Чтобы получить общий прямоугольник без линий, вы можете использовать морфологическое преобразование, такое как закрытие. Вот пример:

# Threshold with a broader HSV range 
thresh = cv2.inRange(hsv, (10, 80, 0), (20, 140, 255))

kernel = np.ones((10, 10), np.uint8)
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)

Вот контур, полученный с использованием draw_countours(), определенного выше:

Вы можете обрезать изображение, используя прямоугольник bbox. Обязательно удалите все контуры шума, чтобы сохранить только основной интересующий контур.

cnts, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

rects = [cv2.boundingRect(cnt) for cnt in cnts if cv2.contourArea(cnt) > area_treshold]
x, y, w, h = rects[0]

crop = image[y:y+h, x:x+w]

большое спасибо, я попробовал это, однако есть и другие таблицы с другими цветами, но я думаю, что мне придется пройти трудный путь,

ovu sunday 30.03.2023 17:34

есть ли способ извлечь или обрезать всю таблицу. это заголовки и тело в целом

ovu sunday 30.03.2023 17:36

@ovusunday я отредактировал свой ответ на ваш новый вопрос

thmslmr 30.03.2023 18:32

Другие вопросы по теме