найти оптимальное прилегание одной формы внутри другой не является тривиальным, но если вы можете решить для неоптимального результата вы можете сделать следующее:
import cv2
import numpy as np
from matplotlib import pyplot as plt
bg_contours, bg_hierarchy = cv2.findContours(bg_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
bg_contour = bg_contours[0]
bg_ellipse = cv2.fitEllipse(bg_contour)
p_contours, p_hierarchy = cv2.findContours(fruit_alpha, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
pear_hull = cv2.convexHull(p_contours[0])
pear_ellipse = cv2.fitEllipse(pear_hull)
min_ratio = min(bg_ellipse[1][0]/pear_ellipse[1][0], bg_ellipse[1][1]/pear_ellipse[1][1])
x_shift = bg_ellipse[0][0] - pear_ellipse[0][0] * min_ratio
y_shift = bg_ellipse[0][1] - pear_ellipse[0][1] * min_ratio
(эвристический) Изменение размера фруктового контура, начните с начальным приближением на основе эллипсов, уточнить с помощью контура (это может быть улучшено, но это не тривиальная задача оптимизации, вы можете посмотреть более here):
r_contour = np.array([[[int(j) for j in i[0]]] for i in min_ratio * p_contours[max_c_ix]])
min_dist, bad_pt = GetMinDist(outer_contour=bg_contour, inner_contour=r_contour, offset=(int(x_shift), int(y_shift)))
mask_size = max(bg_ellipse[1][0], bg_ellipse[1][1])
scale = min_ratio * (mask_size + min_dist)/mask_size
r_contour = np.array([[[int(j) for j in i[0]]] for i in scale * p_contours[max_c_ix]])
Объедините изображения с помощью альфа-канала:
combined = CombineImages(bg, fruit_rgb, fruit_alpha, scale, (int(x_shift), int(y_shift)))
Подсобные функции:
def GetMinDist(outer_contour, inner_contour, offset):
min_dist = 10000
bad_pt = (0,0)
for i_pt in inner_contour:
#pt = (float(i_pt[0][0]), float(i_pt[0][1]))
pt = (i_pt[0][0] + int(offset[0]), i_pt[0][1] + int(offset[1]))
dst = cv2.pointPolygonTest(outer_contour, pt, True)
if dst < min_dist:
min_dist = dst
bad_pt = pt
return min_dist, bad_pt
def CombineImages(mask_img, fruit_img, fruit_alpha, scale, offset):
mask_height, mask_width, mask_dim = mask_img.shape
combined_img = np.copy(mask_img)
resized_fruit = np.copy(mask_img)
resized_fruit[:] = 0
resized_alpha = np.zeros((mask_height, mask_width), fruit_alpha.dtype)
f_height, f_width, f_dim = fruit_img.shape
r_fruit = cv2.resize(fruit_img, (int(f_width*scale), int(f_height*scale)))
r_alpha = cv2.resize(fruit_alpha, (int(f_width*scale), int(f_height*scale)))
height, width, channels = r_fruit.shape
roi_x_from = offset[0]
roi_x_to = offset[0] + width
roi_y_from = offset[1]
roi_y_to = offset[1] + height
resized_fruit[roi_y_from:roi_y_to, roi_x_from:roi_x_to, :] = r_fruit
resized_alpha[roi_y_from:roi_y_to, roi_x_from:roi_x_to] = r_alpha
for y in range(0,mask_height):
for x in range(0, mask_width):
if resized_alpha[y,x] > 0:
combined_img[y,x,:] = resized_fruit[y,x,:]
return combined_img
Я надеюсь, что помогает.
(я опустил части кода, которые не способствуют пониманию потока)
ROI означает Rect интереса. вы меняете свой вопрос, чтобы его понимали. – sturkmen
@sturkmen Да .. У меня есть 2 изображения. И одно изображение должно соответствовать ROI другого изображения. – Neeraj
@sturkmen Roi означает область интереса ... – Neeraj