opencv

作者: nnlrl | 来源:发表于2020-05-28 09:04 被阅读0次

    投影变换

    使用opencv实现投影变换,对图片进行预处理,灰度转换,高斯模糊,canny边缘检测(找到需要投影的区域),在边缘检测的基础上获得投影区域的连通域,计算周长并使用approxPolyDP将连续光滑曲线折线化寻找拐点,随后对指定区域使用投影变换进行投影。

    # 先定义一个组合图片的函数,也可以使用matplotlib进行组图
    def stackImages(scale,imgArray):
        rows = len(imgArray)
        cols = len(imgArray[0])
        rowsAvailable = isinstance(imgArray[0], list)
        width = imgArray[0][0].shape[1]
        height = imgArray[0][0].shape[0]
        if rowsAvailable:
            for x in range ( 0, rows):
                for y in range(0, cols):
                    if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:
                        imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
                    else:
                        imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
                    if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
            imageBlank = np.zeros((height, width, 3), np.uint8)
            hor = [imageBlank]*rows
            hor_con = [imageBlank]*rows
            for x in range(0, rows):
                hor[x] = np.hstack(imgArray[x])
            ver = np.vstack(hor)
        else:
            for x in range(0, rows):
                if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
                    imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
                else:
                    imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
                if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
            hor= np.hstack(imgArray)
            ver = hor
        return ver
    
    import cv2
    import numpy as np
    
    # 预处理改变图片尺寸
    #####################################
    widthImg = 600
    heightImg = 800
    #####################################
    
    img = cv2.imread('nnlrl-Learn-OpenCV-in-3-hours-master/Learn-OpenCV-in-3-hours/Resources/paper.jpg')
    
    def preprocessing(img):
        imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 灰度转换
        imgBlur = cv2.GaussianBlur(imgGray, (5, 5), 1) # 高斯模糊
        imgCanny = cv2.Canny(imgBlur, 200, 200) # canny边缘检测
    
        kernel = np.ones((5, 5)) # 进行膨胀和腐蚀操作,增加边缘厚度
        imgDilate = cv2.dilate(imgCanny, kernel, iterations=2) # 迭代两次膨胀操作,
        imgErode = cv2.erode(imgDilate, kernel, iterations=1) # 迭代依次腐蚀操作
        return imgErode
    
    cv2.imshow('image', img)
    cv2.imshow('imgErode', imgErode)
    
    image
    # 获取目标区域的连通域, 计算面积寻找大于5000并且是矩形的区域  
    def get_contours(img):
        biggest = np.array([])
        maxArea = 0
        contours, hierarchy = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
        for cnt in contours:
            area = cv2.contourArea(cnt)
            if area > 5000:
                #cv2.drawContours(imgContour, cnt, -1, (255, 0, 0), 3)
                peri = cv2.arcLength(cnt,True)
                approx = cv2.approxPolyDP(cnt,0.02*peri,True)
                if area > maxArea and len(approx) == 4:
                    biggest = approx
                    maxArea = area
        cv2.drawContours(img_contour, biggest, -1, (255, 0, 0), 20)
        return biggest
    
    
    # 进行投影变换,由于返回的拐点顺序有问题,需要使用helper函数reorder对拐点进行重新排序
    def get_wrapped(img, biggest):
        biggest = reorder(biggest)
        print(biggest.shape)
        pts1 = np.float32(biggest)
        pts2 = np.float32([[0, 0], [widthImg, 0], [0, heightImg], [widthImg, heightImg]])
        matrix = cv2.getPerspectiveTransform(pts1, pts2)
        img_output = cv2.warpPerspective(img, matrix, (widthImg, heightImg))
    
        img_cropped = img_output[20:img_output.shape[0]-20, 20:img_output.shape[1]-20]
        img_cropped = cv2.resize(img_cropped, (widthImg, heightImg))
    
        return img_cropped
    
    def reorder(biggest):
        my_points = biggest.reshape((4, 2))
        my_points_new = np.zeros((4, 1, 2), np.int32)
        _sum = my_points.sum(1)
        my_points_new[0] = my_points[np.argmin(_sum)]
        my_points_new[3] = my_points[np.argmax(_sum)]
        diff = np.diff(my_points, axis=1)
        my_points_new[1] = my_points[np.argmin(diff)]
        my_points_new[2] = my_points[np.argmax(diff)]
        print(my_points_new)
    
        return my_points_new
    
    img = cv2.resize(img,(widthImg,heightImg))
    
    imgpreprocessing = preprocessing(img)
    img_contour = img.copy()
    biggest = get_contours(imgpreprocessing)
    img_output = get_wrapped(img, biggest)
    
    img_stack = stackImages(0.6, ([img, imgpreprocessing], [img_contour, img_output]))
    
    cv2.imshow('result', img_stack)
    cv2.waitKey(0)
    
    result

    相关文章

      网友评论

          本文标题:opencv

          本文链接:https://www.haomeiwen.com/subject/qkpiahtx.html