gpt4 book ai didi

opencv - 使用 OpenCV 的视角和光照条件略有不同的两幅图像之间的差异

转载 作者:行者123 更新时间:2023-12-04 04:27:10 25 4
gpt4 key购买 nike

使用 CV - Extract differences between two images 中解释的方法我们可以识别两个对齐图像之间的差异。
当摄像机角度(视角)和光照条件略有不同时,如何使用 OpenCV 做到这一点?
来自 How to match and align two images using SURF features (Python OpenCV )? 的代码有助于旋转/对齐两个图像,但由于透视变换(“单应性”)的结果并不完美,“差异”算法在这里不能很好地工作。
例如,如何从这 2 张照片中仅获得绿色贴纸(= 差异)?
enter image description here enter image description here

最佳答案

对于两个图像的对齐,您可以使用仿射变换。为此,您需要来自两个图像的三个点对。为了获得这些点,我将使用对象角。这是我为获得角落而遵循的步骤。

  • 高斯混合模型的背景减法(或对象提取)
  • 第一步输出的降噪
  • 使用轮廓获取角点

  • 我将使用 opencv 库来实现所有这些功能。
    import cv2
    from sklearn.mixture import GaussianMixture as GMM
    import matplotlib.pyplot as plt
    import numpy as np
    import math


    def extract_object(img):

    img2 = img.reshape((-1,3))

    n_components = 2

    #covariance choices: full, tied, diag, spherical
    gmm = GMM(n_components=n_components, covariance_type='tied')
    gmm.fit(img2)
    gmm_prediction = gmm.predict(img2)

    #Put numbers back to original shape so we can reconstruct segmented image
    original_shape = img.shape
    segmented_img = gmm_prediction.reshape(original_shape[0], original_shape[1])

    # set background always to 0
    if segmented_img[0,0] != 0:
    segmented_img = cv2.bitwise_not(segmented_img)
    return segmented_img


    def remove_noise(img):
    img_no_noise = np.zeros_like(img)

    labels,stats= cv2.connectedComponentsWithStats(img.astype(np.uint8),connectivity=4)[1:3]

    largest_area_label = np.argmax(stats[1:, cv2.CC_STAT_AREA]) +1

    img_no_noise[labels==largest_area_label] = 1
    return img_no_noise

    def get_box_points(img):
    contours, _ = cv2.findContours(img.astype(np.uint8), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    cnt = contours[0]
    rect = cv2.minAreaRect(cnt)
    box_points = cv2.boxPoints(rect)
    box_points = np.int0(box_points)

    return box_points

    img = cv2.imread('choco.jpg',1)
    img_paper = cv2.imread('choco_with_paper.jpg',1)

    # remove background
    img_bg_removed = extract_object(img)
    img_paper_bg_removed = extract_object(img_paper)

    background removed
    img_no_noise = remove_noise(img_bg_removed)
    img_paper_no_noise = remove_noise(img_paper_bg_removed)

    img_box_points = get_box_points(img_no_noise)
    img_paper_box_points = get_box_points(img_paper_no_noise)
    detected corners
    图像的四角略微偏离,但对于这项任务来说已经足够了。我确信有更好的方法来检测角落,但这对我来说是最快的解决方案:)
    接下来,我将应用仿射变换将原始图像与纸上的图像配准/对齐。
    # Affine transformation matrix
    M = cv2.getAffineTransform(img_box_points[0:3].astype(np.float32), img_paper_box_points[0:3].astype(np.float32))

    # apply M to the original binary image
    img_registered = cv2.warpAffine(img_no_noise.astype(np.float32), M, dsize=(img_paper_no_noise.shape[1],img_paper_no_noise.shape[0]))

    # get the difference
    dif = img_registered-img_paper_no_noise

    # remove minus values
    dif[dif<1]=0
    这是纸张图像和注册原始图像之间的区别。
    difference between the paper image and the registered original image
    我所要做的就是在这些区域中获得最大的组件(即这张纸),并应用一个凸包来覆盖这张纸的大部分。
    dif = remove_noise(dif) # get the largest component
    contours, _ = cv2.findContours(dif.astype(np.uint8), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    drawing = dif.copy().astype(np.uint8)

    hull = [cv2.convexHull(contours[0])]

    cv2.drawContours(drawing, hull, 0, 255,-1)

    img_paper_extracted = cv2.bitwise_and(img_paper,img_paper,mask=drawing)
    这是我的最终结果。
    paper extracted

    关于opencv - 使用 OpenCV 的视角和光照条件略有不同的两幅图像之间的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67736244/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com