Обрезка некоторой области на картинке Python
Есть картинка с желтым залитым кругом на черном фоне
Пример:
Каким способом можно обрезать эту картинку до краев круга, чтобы получилось такое(картинка немного растянулась):
Если нужно, картину с кругом на черном фоне получаю из такой
Вот таким кодом:
import numpy as np
import cv2 as cv
hsv_min = np.array((0, 77, 17), np.uint8)
hsv_max = np.array((208, 255, 255), np.uint8)
if __name__ == '__main__':
fn = 'buttons/bar.png'
img = cv.imread(fn)
hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)
thresh = cv.inRange(hsv, hsv_min, hsv_max)
contours0, hierarchy = cv.findContours(thresh.copy(), cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
file_num = 0
for cnt in contours0:
if len(cnt) > 4:
# create a new image with same dimensions as original image
ellipse_img = np.zeros((img.shape[0], img.shape[1], 3), dtype = "uint8")
print(cnt)
ellipse = cv.fitEllipse(cnt)
cv.ellipse(ellipse_img, ellipse, (255, 255, 255), 2)
# save new image
filename = 'ellipse' + str(file_num) + '.jpg'
cv.imwrite(filename, ellipse_img)
# increment counter in filename
file_num += 1
Ответы (2 шт):
Обычная задача на нахождение объекта перед тем, как его сможет обработать нейронная сеть. Как я понял, у вас довольно статическое изображение: то есть отсутствует деформация формы в виде небольшого растяжения объекта и подобные штучки, подрывающие все основно. Для таких случаев я бы порекомендовал CNN сети, однако это довольно дорого для вашей задачи. Вы уже смотрели в сторону cv2.matchTemplate(image, template, method)? По мне так идеальное решение. Для начала в редакторе графики кропнем сам кружок, после обработаем изображение в терминале как то так:
import cv2
file=r"template.png"
gray=cv2.imread(file, cv2.IMREAD_GRAYSCALE)
(_ret, thresh)=cv2.threshold(gray, 170, 255, cv2.THRESH_BINARY)
cv2.imwrite(file, thresh)
То есть сохраним его как одноканальный threshold и больше не мучаемся с этим. Это мы получили шаблон объекта, который ищем. Что то такое:

Приведу небольшой пример того, как можно найти координаты объекта:
import cv2
class files:
image =r"image.png"
template =r"template.png"
""" Для нашей задачи достаточно сразу читать все в GRAYSCALE и не морочиться с переводом в него.
Вот тут осторожней: один канал у template и три у image.
Нужно threshold или Candy( или как его там.. ) применить на image.
"""
image =cv2.imread(files.image, cv2.IMREAD_GRAYSCALE)
template =cv2.imread(files.template, cv2.IMREAD_ANYDEPTH)
(_ret, threshold)=cv2.threshold(image, 170, 255, cv2.THRESH_BINARY)
""" Можно поиграть с методами (3 аргумент),
наиболее подходящими вам.
"""
match=cv2.matchTemplate(threshold, template, cv2.TM_CCOEFF_NORMED)
""" Теперь нам совсем просто получить начальные координаты найденного совпадения с шаблоном.
Я реализую это принимая за внимание наличие только одоного круга.
Однако, если ваша задача предполагает наличие нескольких кругов на изображении,
то можно воспользоваться этим:
location=numpy.where(match >= 0.9)
for y, x in zip(*location):
код
Поиграйте со значением 0.9 и все должно получиться.
//
max_loc, (x, y) - левые верхние координаты.
Прибавим к этому размер template и получим правые нижние.
"""
(_min_val, _max_val, _min_loc, max_loc)=cv2.minMaxLoc(match)
left_upper =max_loc
right_lower =\
( left_upper[0] + template.shape[0],
left_upper[1] + template.shape[1]
)
""" Для наглядности вырежим этот фрагмент и покажем в окне:
"""
this_object=image[ left_upper[1]:right_lower[1], left_upper[0]:right_lower[0] ]
cv2.imshow("this_object", this_object)
cv2.waitKey(0)
Диапазон для inRange выбран изначально неверно и можно сделать сильно проще:
import numpy as np
import cv2 as cv
hsv_min = np.array((18, 200, 200), np.uint8)
hsv_max = np.array((23, 255, 255), np.uint8)
fn = '6dd0L.png' # полная картинка
img = cv.imread(fn)
hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)
thresh = cv.inRange(hsv, hsv_min, hsv_max)
output = cv.connectedComponentsWithStats(thresh, 8, cv.CV_32S)
stats = output[2]
i=np.argmax(stats[1:,4])+1
crop=img[stats[i,1]:stats[i,1]+stats[i,3], stats[i,0]:stats[i,0]+stats[i,2],:]
cv.imshow('test', crop)
Вырезается наибольший по площади оранжевый объект на картинке и все.

