【问题标题】:Fitting an Image to a ROI将图像拟合到 ROI
【发布时间】:2016-08-18 16:41:03
【问题描述】:

我有一个 ROI 和一个图像。我必须用我拥有的图像填充 ROI。图像应根据 ROI 形状和大小进行缩放,并且应填充整个 ROI,而不重复图像。如何使用 opencv 实现这一点? opencv中有什么方法可以实现吗?

假设这个白色部分是我的投资回报率和

这是我的输入图像

有没有使用imageMagick的解决方案???

【问题讨论】:

  • ROI 表示感兴趣的矩形。您应该编辑您的问题以便理解。
  • @sturkmen 是的.. 我有 2 张图片.. 一张图片应该适合另一张图片的 ROI
  • @sturkmen Roi 表示感兴趣的区域...
  • 你说得对,对不起,但在 OpenCV 中通常表示一个矩形区域。你是否愿意只适合两个形状的矩形区域?
  • 其他看this sample。我试图运行,但它给出了一个错误。也许this 会有所帮助。

标签: c++ opencv image-processing imagemagick opencv3.0


【解决方案1】:

找到一种形状与另一种形状的最佳匹配并非易事,但如果您能满足于次优结果,您可以执行以下操作:

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]])

使用 alpha 通道组合图像:

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

希望对你有帮助。

(我省略了不利于理解流程的部分代码)

【讨论】:

  • 一系列功能清晰呈现。为什么这个答案没有得到验证?
猜你喜欢
  • 1970-01-01
  • 2011-08-26
  • 1970-01-01
  • 1970-01-01
  • 2021-04-17
  • 2015-04-01
  • 2011-02-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多