admin 管理员组

文章数量: 1087131

滑动窗口切割图片并重定位标注框

在进行目标检测时候,尤其是小目标检测,将图片放大后再进行检测是一个常用的手段,但是方法的后的图像在输入网络的时候,有会被resize带一定得尺寸,这样的我们的放大就没有起到作用。所以有时候我们需要将图片放大后,使用滑动窗口切割产生多幅图像,然后再输入到网络中进行学习。在放大图像和切割图像的过程中,我们需要同时调整标注框。
下面分享一下我写的放大和滑动窗口切割图像的python代码:

#coding:utf-8
import cv2
import os
import codecsdef zomImg(impath, boxes, scale):#print(impath)img = cv2.imread(impath) #G:/head_dataset/head_train/images/UCSD/train_data/vidd1_33_018_f009.jpgheight,width,c = img.shaperesizeImg = cv2.resize(img,(int(width*scale),int(height*scale)),interpolation=cv2.INTER_LINEAR)for i in range(len(boxes)):nw = boxes[i][2] * scalenh = boxes[i][3] * scalecenterx = (boxes[i][0] + boxes[i][2] / 2)centery = (boxes[i][1] + boxes[i][3] / 2)boxes[i][0] = (centerx * scale - nw / 2) if (centerx * scale - nw / 2) > 0 else 0boxes[i][1] = (centery * scale - nh / 2) if (centery * scale - nh / 2) > 0 else 0boxes[i][2] = nwboxes[i][3] = nhreturn resizeImg, boxes#overlap_half=True滑动窗口切图,每次有一半区域重叠,这时候x方向的步长就是窗口宽度的一半,y方向的步长是窗口高度的一半,stridex和stridey参数将不再起作用
def slide_crop(img,kernelw,kernelh,overlap_half=True,stridex=0,stridey=0):height, width, _ = img.shapeif overlap_half:stridex = kernelw / 2stridey = kernelh / 2img_list = []corner_list = []stepx = int(width / stridex)stepy = int(height / stridey)for r in range(stepy-1):startx = 0starty = r * strideyfor c in range(stepx-1):startx = c*stridexcorner_list.append((startx,starty))img_list.append(img[starty:starty+kernelh,startx:startx+kernelw,:])return img_list,corner_listdef show_box(img,boxes):for box in boxes:cv2.rectangle(img, (box[0],box[1]), (box[0]+box[2],box[1]+box[3]), (0, 255, 0), 1)cv2.imshow('image',img)cv2.waitKey(0)def crop_dataset(imgpath, scale, annotation, cropAnno, savePath,dataset,sub=''):savePath = os.path.join(savePath, dataset+sub+'_crop_'+str(scale))if os.path.exists(savePath) is False:os.mkdir(savePath)with codecs.open(annotation,'r',encoding='utf-8') as f:annotationList = f.readlines()count = 0with codecs.open(os.path.join(cropAnno,'head_train_'+dataset+'_crop_'+str(scale)+'_bbx_gt.txt'),'w',encoding='utf-8') as f:while count < len(annotationList):name = annotationList[count].strip('\n')print(name)count += 1num = int(annotationList[count])count += 1boxes = []for i in range(num):box = []for point in annotationList[count].split(' ')[0:-1]:box.append(int(point))boxes.append(box)count += 1resizeImg, boxes = zomImg(imgpath +'/'+ name, boxes, scale)#show_box(resizeImg, boxes)height, width, _ = resizeImg.shapekernelw = width / scalekernelh = height / scaleimg_list, corner_list = slide_crop(resizeImg,kernelw,kernelh,overlap_half=True)boxes_list = [[] for i in range(len(corner_list))]for i, (x, y) in enumerate(corner_list):for box in boxes:if(box[0] >= x and box[1] >= y and (box[0]+box[2]) <= (x + kernelw) and (box[1]+box[3]) <= (y + kernelh)): #被切开的标注框过滤掉rescale_box = [] #注意python中引用rescale_box.append(box[0] - x)rescale_box.append(box[1] - y)rescale_box.append(box[2])rescale_box.append(box[3])boxes_list[i].append(rescale_box)name_split = name.split('/')i = 0name_list = []for img in img_list:img_name = name.split('/')[1] + '/' + name_split[2].split('.')[0] + '_' + str(i) + '.' + name_split[2].split('.')[-1]#print(savePath + '/' +name.split('/')[1]+ '/' + name_split[2].split('.')[0]+'_'+str(i)+'.'+name_split[2].split('.')[-1])#cv2.imwrite(savePath + '/'+name.split('/')[1]+'/' +name_split[2].split('.')[0]+'_'+str(i)+'.'+name_split[2].split('.')[-1],img)print(savePath + '/' + img_name)cv2.imwrite(savePath + '/' + img_name, img)name_list.append(dataset+'_crop_'+str(scale)+'/'+img_name)i += 1for i,img_name in enumerate(name_list):boxes = boxes_list[i]if len(boxes) == 0: #没有目标的图片不写标注文件continuef.write(img_name+'\n')f.write(str(len(boxes)) + '\n')for box in boxes:f.write(str(box[0])+' '+str(box[1])+' '+str(box[2])+' '+str(box[3])+'\n')if __name__ == '__main__':dataset = 'Part_A'scale = 2imgpath = 'G:/head_dataset/head_train/images'annotation = 'G:/head_dataset/head_split/head_train_' + dataset + '_bbx_gt.txt'cropAnno = 'G:/head_dataset/head_crop/split/'savePath = 'G:/head_dataset/head_crop/images/'crop_dataset(imgpath, scale, annotation, cropAnno, savePath, dataset, sub='')

原图的标注文件head_train_’ + dataset + '_bbx_gt.txt是这种形式的:

Part_B/val_data/IMG_335
23 #标注框的个数
0 540 96 96  # x,y,w,h
96 652 126 126 
85 265 78 78 
215 294 96 96 
289 266 109 109 
392 378 109 109 
859 702 93 93 
502 178 57 57 
301 153 60 60 
220 150 47 47 
200 12 26 26 
254 17 26 26 
278 12 26 26 
290 60 26 26 
315 73 26 26 
348 69 38 38 
431 62 45 45 
672 79 52 52 
294 0 26 26 
324 1 26 26 
652 129 52 52 
630 87 52 52 
402 7 38 38 

可视化后是这样的:
切割放大两倍后滑动切割,每次滑动重叠一半会产生9张图,产生的标注框是这样的:




本文标签: 滑动窗口切割图片并重定位标注框