Как найти прямоугольники на изображении?
Есть такой скрипт
import cv2
import numpy
from PIL import Image
"""
# параметры цветового фильтра
hsv_min = numpy.array((0, 70, 150), numpy.uint16)
hsv_max = numpy.array((255, 255, 255), numpy.uint16)
"""
# параметры цветового фильтра
hsv_min = numpy.array((0, 70, 150), numpy.uint8)
hsv_max = numpy.array((255, 255, 255), numpy.uint8)
class ImageCandlesProcessing(object):
def __init__(self, image):
super().__init__()
pil_image = image
numpy_array = numpy.array(pil_image)
# convert to a openCV2 image, notice the COLOR_RGB2BGR which means tha
# the color is converted from RGB to BGR format
self.opencv_image = cv2.cvtColor(numpy_array, cv2.COLOR_RGB2BGR)
self.boxes = []
def preparation(self):
hsv = cv2.cvtColor(self.opencv_image, cv2.COLOR_BGR2HSV) # меняем цветовую модель с BGR на HSV
self.thresh = cv2.inRange(hsv, hsv_min, hsv_max) # применяем цветовой фильтр
def find_contours(self):
# ищем контуры и складируем их в переменную contours
(contours, hierarchy) = cv2.findContours(self.thresh.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for contour in contours:
cv2.boundingRect(contour)
rectangle = cv2.minAreaRect(contour)
box = cv2.boxPoints(rectangle)
box = numpy.int0(box)
self.boxes.append(box)
def draw_contours(self):
for box in self.boxes:
cv2.drawContours(self.opencv_image, [box], 0, (255, 0, 0), 1)
def converting_opencv_to_pil_image(self):
self.image = Image.fromarray(cv2.cvtColor(self.opencv_image, cv2.COLOR_BGR2RGB))
def show_image(self):
cv2.namedWindow("Image", cv2.WINDOW_NORMAL)
cv2.resizeWindow('Image', 300, 400)
cv2.imshow('Image', self.opencv_image)
cv2.waitKey(0)
"""
image = Image.open("input.png")
image_processing = ImageCandlesProcessing(image)
image_processing.preparation()
image_processing.find_contours()
image_processing.draw_contours()
image_processing.show_image()
"""
Вроде справляется с поиском но иногда не совсем
Вопроса два как оптимизировать код что бы выделялись контуры без учёта теней
И как вырезать эти контуры для дальнейшего анализа то есть цвет и высота
Ответы (1 шт):
По вопросу теней я не понял. Однако это может быть связано с непониманием hsv формата.
# параметры цветового фильтра
hsv_min = numpy.array((0, 70, 150), numpy.uint8)
hsv_max = numpy.array((255, 255, 255), numpy.uint8)
Как я вижу, цвета инициализированы наугад и удачу.
Choosing the correct upper and lower HSV boundaries for color detection withcv::inRange (OpenCV)
Задача определения цвета каждой свечи, по моему, слишком странная. Применить цветовой фильтр дважды и получить две маски свечей по цвету более рационально.
Высоту контура можно получить с помощью cv2.boundingRect(contour). Реализован в Candle.render (см ниже).
Ниже моя реализация нахождения свечей и используемое при ней изображение.
# Дата: July 26th, 2020.
import cv2
import numpy
class Candle:
"""
Контейнер для свечи.
"""
# Типы свечей.
up = "<ядовитая свеча>"
down = "<падать вниз молодцом свеча>"
def __init__(self, type, contour):
self.type = type
self.contour = contour
def render(self, canvas):
x, y, w, h = cv2.boundingRect(self.contour)
color = (2, 235, 25) if self.type == Candle.up else (25, 2, 233)
cv2.rectangle(canvas, (x, y), (x + w, y + h), color, -1)
COLOR_FILTER = \
{ Candle.up: (
numpy.array([60, 100, 30], numpy.uint8),
numpy.array([90, 180, 180], numpy.uint8)),
Candle.down: (
numpy.array((150, 110, 40), numpy.uint8),
numpy.array((170, 170, 170), numpy.uint8)),
}
def Candles(image, debug = False):
# Возвращает список найденных свеч на изображении объектами Candle.
def Extract(type, mask):
# Возвращает список найденных свеч на изображении в местах маски объектами Candle.
scr = cv2.bitwise_and(image, image, mask = mask)
gray = cv2.cvtColor(scr, cv2.COLOR_BGR2GRAY)
(contours, hierarchy) = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
result = list()
for contour in contours:
result.append(Candle(type, contour))
return result
# Применим цветной фильтр к каждому типу свечи.
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
up = cv2.inRange(hsv, *COLOR_FILTER[Candle.up])
down = cv2.inRange(hsv, *COLOR_FILTER[Candle.down])
# К просмотру предварительного результата.
if debug:
cv2.imshow("up", cv2.bitwise_and(image, image, mask = up))
cv2.imshow("down", cv2.bitwise_and(image, image, mask = down))
cv2.imshow("common", cv2.bitwise_and(image, image, mask = up + down))
cv2.imshow("other", cv2.bitwise_and(image, image, mask = 255 - (up + down)))
cv2.waitKey(0)
result = list()
result += Extract(Candle.up, up)
result += Extract(Candle.down, down)
return result
if __name__ == "__main__":
file = "7081e63154fd4d56a0c2a00ae5ee116a.py.png"
image = cv2.imread(file)
candles = Candles(image, True)
# Нарисуем найденные свечи сandles.
canvas = numpy.zeros(image.shape, numpy.uint8)
for candle in candles:
candle.render(canvas)
cv2.destroyAllWindows()
cv2.imshow("Out", canvas)
cv2.waitKey(0)
В итоге рисуется холст, который отображает то же самое положение свечей и их тип (по цвету), что и исходное.


