美文网首页蓉蓉的计算机视觉打怪之路
python opencv 从语义分割mask中crop出物体(

python opencv 从语义分割mask中crop出物体(

作者: 涂山容容 | 来源:发表于2019-04-18 19:35 被阅读0次

遇到的问题,给了车道线的mask,需要从图像中把里面的存在的车道线抠出来。
1.首先用find_contours找到所有的物体(这里的话,找到的是连通区域,然后基于前面的车道线可能连在一起,所以取mask的时候把前面的五分之一给去掉了,五分之一是magic number,自己看了图之后定下来的 ),然后把像素少的给过滤了,因为不是想要的。

2.给找到的物体排个序(因为标签是按照车道的顺序打的,没有对像素或者曲线打标签)按照在图像中出现的顺序排序,这里用的是最小框的右上角的坐标+右下角坐标的均值)这样来确定出现的顺序(从左到右边)主要是因为单纯一个坐标不一定准,点会有交叉,在前面的时候,有的画的长,有的画的短,右下的也是。

3.获取到四个物体的各自的边框,由于这个边框是旋转的,所以不能直接crop出来,要做变换(这里的变换可选的有两种,第一种,旋转图片,然后直接crop,但是这里的话要预先对图像做padding的操作,不然的话就会有地方crop不到,部分缺失。第二种的话,直接对box做透视变换。然后用warp perspective来做。这种的话也要padding,但是不padding也能用,就是截取的框超出图片的时候,超出的像素会为0,反正自己padding的话也有可能是补0,所以就没有padding了。

出现的问题:

出来的图有的是横着的,有的是竖的,自己想要的都是竖的。所以后面加了判断,把横的给旋转了。

def crop_rotate_box(cnt,img):

    rect = cv2.minAreaRect(cnt)
    box = cv2.boxPoints(rect)
    box = np.int0(box)

    width = int(rect[1][0])
    height = int(rect[1][1])
    src_pts = box.astype("float32")
    dst_pts = np.array([[0, height - 1],
                        [0, 0],
                        [width - 1, 0],
                        [width - 1, height - 1]], dtype="float32")


    M = cv2.getPerspectiveTransform(src_pts, dst_pts)

  
    warped = cv2.warpPerspective(img, M, (width, height))
    return warped

def rotate_img_with_height_longer(img):
    h, w,_ = img.shape

    if h<w:
        '''getRotationMatrix2D only rotate kepp same ratio'''
        #cv2.getRotationMatrix2D出来的图特别小,是在原始图上截取的,也就是说要先对原图做padding,不然旋转后超出原始图像的像素会不被保留,所以最后改成了np.rot90
        # center = (w / 2, h / 2)
        # M = cv2.getRotationMatrix2D(center,90,1)
        # rotate_img = cv2.warpAffine(img,M,(w,h))
        # h_stack = np.hstack((img, rotate_img))
        rotate_img = np.rot90(img,1)
        # cv2.imshow('img', rotate_img)
        # cv2.waitKey()
        return rotate_img
    else:
        return img

def crop_lane_from_img(img_txt,imagepath, predictionpath,mask_path):
    with open (img_txt,'r') as imgtext:
        img_infos = imgtext.readlines()
        for line in img_infos:
            line = line.strip().split()
            color = [(127, 127, 127), (127, 0, 127), (127, 127, 0), (0, 127, 127)]
            class_label = ['other', 'solid', 'dotted', 'emergency']
            for label in class_label:
                if not(os.path.exists(os.path.join(mask_path,label))):
                    os.makedirs(os.path.join(mask_path,label))

            img = cv2.imread(os.path.join(imagepath, line[0]))
            img_name = line[0].split('.')[0]
            
            pre = cv2.imread(os.path.join(predictionpath, line[0]))
            print(line)
            # print(np.unique(pre))

            mask = np.where(pre > 128, 1, 0)
            
            mask[0:216,:]=0
            mask = np.array(mask, np.uint8)
            final = np.multiply(img, mask)
            mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
            contours, hier = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
            #print(len(contours))
            cnts ={}
            for cidx, cnt in enumerate(contours):
                if cv2.contourArea(cnt) < 3000:
                    continue
                minAreaRect = cv2.minAreaRect(cnt)


                rectCnt = np.int64(cv2.boxPoints(minAreaRect))
                #print(rectCnt[3][0])
                #cnts.append(rectCnt[3][0])
                cnts[cidx] = (rectCnt[1][0]+rectCnt[3][0])/2
                cv2.polylines(img=final, pts=[rectCnt], isClosed=True, color=(0, 0, 255), thickness=3)
            #cnts.sort()
            sort_cnts = sorted(cnts.items(), key = lambda x:x[1])#对字典进行排序

            #print(sort_cnts)
            for idx, key in enumerate(sort_cnts):
                minAreaRect = cv2.minAreaRect(contours[key[0]])

                rectCnt = np.int64(cv2.boxPoints(minAreaRect))

                if idx<4:

                    wrap_img = crop_rotate_box(contours[key[0]], img)
                    rotate_img = rotate_img_with_height_longer(wrap_img)
                    cv2.imwrite(os.path.join(mask_path,class_label[int(line[idx+1])]+'/'+img_name+'_'+str(idx)+
                                '.jpg'), rotate_img)
                    
                else:
                
                    wrap_img = crop_rotate_box(contours[key[0]], img)
                    rotate_img = rotate_img_with_height_longer(wrap_img)
                    cv2.imwrite(os.path.join(mask_path, class_label[0] + '/' + img_name + '_'+str(idx)+'.jpg'),
                                rotate_img)

参考:

https://jdhao.github.io/2019/02/23/crop_rotated_rectangle_opencv/

相关文章

网友评论

    本文标题:python opencv 从语义分割mask中crop出物体(

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