模型训练的数据集的人力节约[偷懒]方案
前言[挖坑]
这是我第二次打字写前言,因为前一次鼠标掉到地上,刚好按到X
关掉了编辑器…….[北理工破防音]现在是6月21号,晚上的23:10,星期二,艹
今天一整个下午和晚上都在做模型训练的数据集的标注,就是在一张图片里框选出要识别的内容[类似手画人脸识别时候脸周围的框],一共4000张。下午请一朋友吃饭连哄带骗替我弄了1500张,临走时我问明天中午还请他吃饭怎么样他连忙拒绝,总之就是这一过程极其痛苦emm[突然想起欠lxy一顿饭,可以再连哄带骗让他给我打工一次]
自然我这种懒虫会想办法减少自己的工作量,于是。。。
键盘监听与模拟[第一步工作]
这个就是随手一写:
1 | import keyboard |
当按下空格时,就会自动按下ctrl+s来保存标注内容,按下右键切换下一张,按下r进入矩形框选模式[空格本身是退出框选进行移动的快捷键,但是空格用起来舒服hhh所以加上了这个]
但是这样仍然需要手动鼠标拖动进行框选,虽然可以自动保存和翻页,但是还是很累,于是有了这个设想。
能不能这样,先拍几张背景图和识别目标的照片,然后对目标图做随机的仿射变换,RGB值随机变化模拟不同光照环境,再进行随机的鱼眼效果处理来更加逼近真实相机拍摄效果,最后叠加在随机的背景图[对背景图做随机RGB波动]的随机位置,根据这组随机数就可以自动计算出应该框选的坐标,于是可以自动同时完成训练数据集的生成和标注。
这样不仅不用人工标注数据集,甚至不需要拍摄大量照片作为数据集
挖坑完毕,开始肝!
最终全自动方案
不着急,坑慢慢填,没看见前面还是ros笔记的文章还空着吗
现在的进度:导入opencv库:
1 | import cv2 |
好了本文结束[doge]
仿射变换
下面步入正题,首先是对识别目标的仿射变换
1 | import cv2 |
这里仅仅进行了平移操作,主要区别在于M的定义:
平移
1 | M = np.float32([[1, 0, 200], [0, 1, 100]]) |
经过仿射变换后的点的坐标是(x+200,y+100),即将整个图像平移(200,100)
旋转
1 | M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 90, 1) |
cv2.getRotationMatrix2D函数可以生成图像旋转的所需要的矩阵
第一个参数是旋转中心,第二个是旋转角度[正数逆时针],第三个是放大倍数
三点定位
1 | cv2.getAffineTransform(src,dst) #返回2*3的转变矩阵 |
举例:
1 | # 原图像中的三组坐标 |
透视变换[3维]
与之前不同的是,我们需要使用另外两个方法getPerspectiveTransform()和warpPerspective(),仿射变换矩阵M变成了3*3矩阵
1 | cv2.getPerspectiveTransform() 返回3*3的转变矩阵 |
举例:
1 | # 原图的四组顶点坐标 |
图像叠加-mask掩模
由于经过变换后的图像周围有黑边,所以需要经过处理去黑边再叠加
如果直接叠加两个图像,图片将改变颜色
所以cv2.add()
并不可行
如果融合两个图像,会得到透明的效果
所以cv2.addWeighted()
也不可行
实现的方法是图像mask掩模
1 | import cv2 |
实现效果:csdn截图叠加在物理课截屏上
在原作者文章基础上做了增加x,y参数的改进,原作者效果图:(图片即原文链接)
并且由于原文章背景白色而仿射变换出现的背景为黑色,所以后面代码做了相应调整
随机缩放
RGB随机化
实际拍摄中不可能光照等环境完全相同,颜色必然有一定偏差,所以这必须模拟出来
亮度对比度
实在没啥意思直接复制了一个
1 | import cv2 |
饱和度
再随手copy一个
1 | import cv2 as cv |
模糊
有的时候相机拍摄会有模糊现象,so:
以下内容引自我博客的文章opencv学习笔记
1 | #中值滤波 |
后面代码采用的方式是随机大小的均值滤波。
整合以上
对图像的处理已经十分逼近实际拍摄情况,下一步就是综合全部编写程序了
仿射变换参数合理性判断算法
首先,使用随机数进行仿射变换时,有可能随机得到的四边形的凹四边形,仿射变换将会出现意外效果,为了判断四边形是否为凸四边形,我的方法是连接对角线,如果其余两点在线段两边则为凸。判断点是否在线段两边,采用向量叉积的方式,如果两组两个向量叉积异号则为在线段两侧,具体计算方法:
1 | if ((x2-x1)*(y4-y1)-(y2-y1)*(x4-x1))*((x3-x1)*(y4-y1)-(y3-y1)*(x4-x1))<0 and ((x1-x2)*(y3-y2)-(y1-y2)*(x3-x2))*((x4-x2)*(y3-y2)-(y4-y2)*(x3-x2))<0 : |
框选坐标计算算法
虽然经过仿射变换,但是图形比例不变,中点依然在对边中点连线的交点,此点即为矩形边框中点。矩形长宽可根据随机数生成四边形的最小外包矩形的一定比例计算,同样由于仿射变换图形比例不变,该比例具体数值即为原图里汉堡占整个图片的大小比例。
求框选长宽:
1 | xx = max(x2, x4) - min(x1, x3) |
求两直线交点:
1 | def calc_abc_from_line_2d(x0, y0, x1, y1): |
按照合适的比例绘制矩形框:
1 | cv2.rectangle(img, (round(x0-xx/4), round(y0-yy/2.5)), (round(x0+xx/4), round(y0+yy/2.5)), (0, 255, 0), 2) |
效果图:
这是已经完成的代码:
main.py
1 | import cv2 |
funcs.py
1 | import random |
视频逐帧保存图片程序
1 | import os |