背景:在车载监控回传的视频里判断该车里是否有猪
解决思路:在回传视频里做物体识别,如果有猪就框出来并且给出一个代表值
day1 2021-10-27
设想:物体识别,并且在图中框出来猪
1.找正样本
最开始对正样本负样本blabla没有概念,所以瞎转
在csdn里搜猪的数据包,找到了一个1447图+标注文件的数据包,因为以前没做过CV类的东西,感觉牛逼,赶紧下载。
下载后就这个样子,所有图片都是裁好的,纯度不错,并在对应的xml文件里生成了对该猪的描述
(后来发现没鸡儿用,因为我不会处理xml)
2.找负样本
csdn搜了一堆猫狗数据,充当负样本,该数据包自带neg.txt
3.对正样本进行灰度处理,并裁减
4.安装opencv
pip install opencv_python
5.样本裁减+灰度处理
import cv2
path = 写你的图片地址比如 "D:/train/new/pos/"
for i in range(1, 1447): 有多少图写写多大范围
print(path+str(i)+'.jpg') 对应的图片路径
img = cv2.imread(path+str(i)+'.jpg', cv2.IMREAD_GRAYSCALE)
img5050 = cv2.resize(img, (100,100))
cv2.imshow("img",img5050)
cv2.waitKey(20)
cv2.imwrite('D:/train/new/pos/pos/'+str(i)+'.jpg', img5050) 给出处理好的图片存储地址
6.对正样本进行描述处理,生成一个pos.txt文件
import os
def create_pos_n_neg():
for img in os.listdir('D:/train/test2/pos'): 图片的路径,
line = 'pos' + '/' + img + ' 1 0 0 100 100\n' 生成对图片的描述
print(line)
with open('D:/train/test2/pos.txt', 'a') as f: 写入的文件
f.write(line)
if __name__ == '__main__':
create_pos_n_neg()
7.此事文件结构应该是这样的,neg放负样本图片,pos放正样本图片,neg.txt描述负样本,pos.txt描述正样本
对应的5个opencv文件是下载来的,https://pan.baidu.com/s/14plhrufj2hQR3Es3aYqoIg
8.用createsample生成pos.vec
打开cmd,切到存放上边这一堆的文件夹下,输入下边的命令
-vec是生产的vec的名字,-info理解为指定vec从哪来的,-num是样本数,-w -h 宽,高
opencv_createsamples.exe -vec pos.vec -info pos.txt -num 1447 -w 100 -h 100
9.出现这个小东西
10.用traincascade进行分类器的训练,首先创建xml文件夹
和上边一样,打开cmd,输入下边命令
-numPos正样本数,-numNeg负样本数,-vec正样本,-bg负样本,-data xml指生成xml文件 -w -h 宽高,如果用LBP就把模型裁成24*24 -numStages层数,可任意
opencv_traincascade.exe -data xml -vec pos.vec -bg neg.txt -numPos 1447 -numNeg 2000 -numStages 20 -w 100 -h 100 -minHitRate 0.9999 -maxFalseAlarmRate 0.5 -mode ALL
此处记录自己踩的坑
1.numPos没有大写P
2.样本太大内存装不下,一训练就崩溃(解决方法,乖乖把图片裁小点比如20*20)
3.层数太多内存装不下
11.训练完成
在xml文件夹里出现这个东西就说明训练ok
12.整一段代码引用cascade来识别一下视频里的猪
from PIL import Image, ImageDraw, ImageFont
import cv2
import numpy as np
import time
# 由于直接用opencv显示中文会乱码,所以先将图片格式转化为PIL库的格式,用PIL的方法写入中文,然后在转化为CV的格式
def change_cv2_draw(image, strs, local, sizes, colour):
cv2img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
pilimg = Image.fromarray(cv2img)
draw = ImageDraw.Draw(pilimg)
font = ImageFont.truetype("SIMYOU.TTF", sizes, encoding="utf-8") # SIMYOU.TTF为字体文件
draw.text(local, strs, colour, font=font)
image = cv2.cvtColor(np.array(pilimg), cv2.COLOR_RGB2BGR)
return image
# src为输入的图像
# classifier为对应识别物体的分类器
# strs为识别出的物体的中文说明
# colors表示框的颜色
# minSize为识别物体的最小尺寸,当识别的物体尺寸低于这个尺寸,则不检测,就当没识别到
# minSize为识别物体的最大尺寸,当大于该尺寸时不识别
def myClassifier(src, classifier, strs, colors, minSize, maxSize):
gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
# detectMultiScale()方法里面的参数在另一篇博客中有详解:https://blog.csdn.net/GottaYiWanLiu/article/details/90442274
obj = classifier.detectMultiScale(gray, scaleFactor=1.15, minNeighbors=5, minSize=minSize, maxSize=maxSize)
for (x, y, w, h) in obj:
cv2.rectangle(src, (x, y), (x + w, y + w), colors, 2) # 画框,(x,y)为识别物体的左上角顶点,(w,h)为宽和高
src = change_cv2_draw(src, strs, (x, y - 20), 20, colors) # 显示中文
return src
# cap=cv2.VideoCapture(0)
cap = cv2.VideoCapture("C:/train/pigtest.mp4") #这里是对应的视频文件
pig = cv2.CascadeClassifier("C:/train/pig/xml/cascade.xml") 这里是对应的cascade
while True:
_, frame = cap.read()
frame = myClassifier(frame, pig, "pig", (0, 0, 255), (100, 100), (800, 800))
这里的pig是描述框的标题
cv2.imshow("frame", frame)
cv2.waitKey(30)
13. 看看效果
rnm退钱!垃圾垃圾垃圾垃圾