拼接后裁剪图像

问题描述 投票:0回答:3

使用 OpenCV C++ 缝合 2 个图像后,我想裁剪图像以去除缝合图像周围的黑色区域。我会丢失图像的一部分,但没关系。图像看起来像这样:

enter image description here

如何找到图像角点并裁剪所有黑色区域?

如果有什么好的参考资料,请提供给我。

问候,

c++ opencv crop opencv-stitching
3个回答
4
投票

我一直在使用 DJI 开发指南中的这段代码(搜索“裁剪全景图”部分)。 https://dji-dev.gitbooks.io/mobile-sdk-tutorials/content/en/iOS/PanoDemo/PanoDemo_en.html#stitching-photos

乍一看,该算法似乎不是很强大,但到目前为止,它已被证明足以满足我的拼接用例。但是,我相信代码在这两行上有一些错误

bool isBottomNotBlack=checkBlackRow(gray, roiRect.y+roiRect.height,roiRect);
bool isRightNotBlack=checkBlackColumn(gray, roiRect.x+roiRect.width,roiRect);

应该改为

bool isBottomNotBlack=checkBlackRow(gray, roiRect.y+roiRect.height-1,roiRect);
bool isRightNotBlack=checkBlackColumn(gray, roiRect.x+roiRect.width-1,roiRect);

否则,你可能会得到非系统C的坏超额误差。 希望有帮助!


0
投票

裁剪现已集成到 opencv_stitching_tool


0
投票

这里是裁剪全景图像的黑色或白色背景区域的Python代码:

import cv2 as cv
import numpy as np
import imutils
import glob
from numba import jit


def crop_stitched_image (stitched, canvas_color = 'black'):

    # Print cropping
    print("[INFO] cropping...")
    
    # Initilize the variables
    w = stitched.shape[1]
    h = stitched.shape[0]
    
    # Convert the stitched image to grayscale and threshold it
    # such that all pixels greater than zero are set to 255
    # (foreground) while all others remain 0 (background)
    gray = cv.cvtColor(stitched, cv.COLOR_BGR2GRAY)
    if canvas_color == 'black':
        thresh = cv.threshold(gray, 5, 255, cv.THRESH_BINARY)[1]
    else:
        thresh = cv.threshold(gray, 254, 255, cv.THRESH_BINARY_INV)[1]   
    
    # Find all external contours in the threshold image then find
    # the *largest* contour which will be the contour/outline of
    # the stitched image
    cnts = cv.findContours(thresh.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)
    cnts = imutils.grab_contours(cnts)
    c = max(cnts, key=cv.contourArea)
    
    # Mask or stencil
    stencil_inner = np.zeros(stitched.shape, dtype=np.uint8)
    cv.fillPoly(stencil_inner, pts =[c], color=(255,255,255)) 
    stencil_outer = ~stencil_inner
    
    # Canvas outer indices
    canvas_outer_indices = np.where(stencil_outer == [255])

    # Normalize the image to -1 and others
    stitched = np.asarray(stitched, dtype=np.float32)    
    stitched[canvas_outer_indices] = -255
    stitched = stitched / 255.0


    @jit(nopython=True)
    def bulkRun():
        maxarea = 0
        height = np.zeros((w)).astype(np.int32) 
        left = np.zeros((w)).astype(np.int32) 
        right= np.zeros((w)).astype(np.int32) 
                
        ll = 0
        rr = 0 
        hh = 0 
        nl = 0
    
        for line in range(h):
            for k in range(w):
                p = stitched[line][k]
                m = max(max(p[0], p[1]), p[2])
                height[k] =  0 if m < 0 else height[k] + 1  #find Color::NO
                
    
            for k in range(w):
                left[k] = k;            
                while ((left[k] > 0) and (height[k] <= height[left[k] - 1])):
                    left[k] = left[left[k] - 1]
                    
            for k in range(w - 1, -1, -1):
                right[k] = k
                while ((right[k] < w - 1) and (height[k] <= height[right[k] + 1])):
                    right[k] = right[right[k] + 1]
                    
            for k in range(w):
                val = (right[k] - left[k] + 1) * height[k]
                if(maxarea < val):
                    maxarea = val
                    ll = left[k] 
                    rr = right[k]
                    hh = height[k] 
                    nl = line
        
        return ll, rr, hh, nl
    
    ll, rr, hh, nl = bulkRun()
    
    cropH = hh + 1
    cropW = rr - ll + 1
    offsetx = ll
    offsety = nl - hh + 1
    
    stitched *= 255

    return stitched[offsety : offsety + cropH, offsetx : offsetx + cropW].astype(np.uint8)

以下是代码用法:

def main():

    # Read stitched image
    image = cv.imread('result_26.jpg')
        
    # write the output stitched and cropped image to disk
    # stitched_cropped = crop_stitched_image (image, 'white')
    stitched_cropped = crop_stitched_image (image, 'black')
    cv.imwrite('cropped.jpg', stitched_cropped)
        
    print("Done")

if __name__ == '__main__':
    main()
    cv.destroyAllWindows()

我还分别在GitHubMATLAB File Exchange中上传了Python和MATLAB版本。

© www.soinside.com 2019 - 2024. All rights reserved.