я пытаюсь обнаружить некоторые таблицы из изображения, но структура изображений затрудняет использование некоторых библиотек для их извлечения, поэтому я решил извлечь их как изображения, я попытался использовать приведенный ниже код для рисования ограничивающих рамок вокруг прямоугольников, код работает, но, похоже, не обнаруживает прямоугольники более светлых цветов:
это код, который я использую:
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()
это ввод: это входное изображение
если вы заметили на изображении, оно обнаруживает только достаточно темные блоки, а не более светлые блокиэто результат
Любая помощь будет оценена
нет, не делал, как мне это сделать?
Прежде чем преобразовать изображение в оттенки серого с помощью линии gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
, вам нужно будет выяснить исходное значение цвета (например, просмотрев значения изображения в этой конкретной области). При этом вы можете просто сделать что-то вроде (image[is_my_color(image)] = target_color
) с целевым цветом, представляющим собой массив значений BGR несколько более темного цвета np.array([b, g, r])
.
Мы можем 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]
большое спасибо, я попробовал это, однако есть и другие таблицы с другими цветами, но я думаю, что мне придется пройти трудный путь,
есть ли способ извлечь или обрезать всю таблицу. это заголовки и тело в целом
@ovusunday я отредактировал свой ответ на ваш новый вопрос
Привет, вы пытались заменить более светлые пиксели строк таблицы цветом с более высокой контрастностью (например, цветом строки заголовка)?