在做目标检测的时候,需要从拍下来的图片中截取我们的目标,将目标的坐标保存在文档中,方便做训练的时候直接读取图片,截取特定roi区域即可作为正样本投入训练了。
下面是我用python写的一个简单的脚本。
两个函数,一个是鼠标的回调函数,一个是主函数。
回调函数调用全局变量保存矩形框的坐标xmin ymin xmax ymax 还有就是逻辑flag,和图片img;
首先读取图片,显示图片,创建txt文档(坐标写入该文档),当鼠标在图片上按下左键时,触发回调函数的第一个event,表示进入拖动flag , 因为框图的时候我们是要拖动鼠标的,当鼠标一直在拖动的时候回调函数一直在第二个event, 创一个临时temimage 变量保存一开始img的图片, 在临时变量图片中绘矩形框,不然你会看到整个框都是一个颜色(可以试一下); 鼠标拖动结束后,进入第三个event, 便确认了矩形框的最终位置。
这时候在while循环里就可以绘制矩形框了,在原始的img图片上画;
当你按下‘q’ 键时表示退出;
按下‘c’键时表示切换下一张图片,初始化一下imgposition 、重新读取新的img图片即可,图片读完了也退出break;
按下'r' 时表示该图画错矩形框了,需要重新画,初始化一下imgposition 、img 重新读取没有被绘制过的图片即可。
最后销毁窗口,关闭文件。
import cv2
import os
import numpy as np
# 创建鼠标事件的回调函数
def OnMouseAction(event,x,y,flags,param):
global x1, y1, x2, y2, drawflag, img # 调用全局变量
if event == cv2.EVENT_LBUTTONDOWN and drawflag == 0:
x1 = x
y1 = y
drawflag = 1 # 按下标志位
elif event == cv2.EVENT_MOUSEMOVE and (drawflag == 1 or drawflag == 2) :
temImage = img.copy() # 为了不保留绘图轨迹
cv2.rectangle(temImage, (x1, y1), (x, y), (0, 255, 0), 1)
cv2.imshow('PosImage',temImage) # 实时显示拖动矩形框
drawflag = 2 # 拖动标志位
elif event == cv2.EVENT_LBUTTONUP and drawflag == 2:
x2 = x
y2 = y
drawflag = 3 # 按下拖动结束标志位
def main():
print('[q] : Quit the procedure.\n')
print('[c] : Change to next picture.\n')
print('[r] : Restar to draw the rectangle in this picture.\n')
global x1, y1, x2, y2, drawflag, img
drawflag = 0 # 初始化为0
path = './Picture'
imgList=os.listdir(path)
listLen = len(imgList) # 该文件夹图片个数
listNum = 0
img = cv2.imread(os.path.join(path, imgList[listNum]), cv2.IMREAD_COLOR)
restartImg = img.copy() # 重新画的时候用
imgPosition = '' # 整张图片的坐标
cv2.namedWindow('PosImage')
cv2.setMouseCallback('PosImage',OnMouseAction)
txtFile = open('posPicture.txt', 'w')
txtFile.write(imgList[listNum] + ':')
while (True):
if drawflag == 3:
cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 3) # 画矩形框
drawflag = 0 # 回归原始标志位
temPosition = '(' + str(x1) + ',' + str(y1) + ',' + str(x2) + ',' + str(y2) + ')'
imgPosition = imgPosition + temPosition
print(imgList[listNum], temPosition)
if drawflag != 2:
cv2.imshow('PosImage',img)
k=cv2.waitKey(1)
if k==ord('q'):
print('Break.')
break
elif k == ord('c'):
txtFile.write(imgPosition) # 每切换一张图片将前一张坐标写入
listNum = listNum + 1
if listNum >= listLen: # 读取完,跳出
print('Read over.')
break
img = cv2.imread(os.path.join(path, imgList[listNum]), cv2.IMREAD_COLOR) # 读取下一张
txtFile.write('\n' + imgList[listNum] + ':')
imgPosition = '' # 换新的图片坐标清空
print('Change to ', imgList[listNum])
elif k == ord('r'): # 该图重新画框
print('Redraw ', imgList[listNum])
imgPosition = ''
img = cv2.imread(os.path.join(path, imgList[listNum]), cv2.IMREAD_COLOR) # 清空框
cv2.destroyAllWindows()
txtFile.close()
if __name__ == '__main__':
main()