遇到的问题,给了车道线的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/
网友评论