赞
踩
下面来介绍dnn模块的一些函数
dnn.blobFromImage,这是一个图像与处理函数,对你输入进来图像进行预处理
blobFromImage(image, scalefactor, size, mean, swapRB, crop, ddepth)
参数 | 解释 |
---|---|
image | cv2.imread 读取的图片数据 |
scalefactor | 缩放像素值,如 [0, 255] - [0, 1] |
size | 输出blob(图像)的尺寸,如 (netInWidth, netInHeight) |
mean | 从各通道减均值. 如果输入 image 为 BGR 次序,且swapRB=True,则通道次序为 (mean-R, mean-G, mean-B),这么做可以排除光照,噪音对检测的影响 |
swapRB | 交换 3 通道图片的第一个和最后一个通道,如 BGR - RGB |
crop | 图像尺寸 resize 后是否裁剪. 如果crop=True,则,输入图片的尺寸调整resize后,一个边对应与 size 的一个维度,而另一个边的值大于等于 size 的另一个维度;然后从 resize 后的图片中心进行 crop. 如果crop=False,则无需 crop,只需保持图片的长宽比 |
ddepth | 输出 blob 的 Depth. 可选: CV_32F 或 CV_8U |
经过dnn.blobFromImage处理过的图像如果想要直接显示,则还需还需np.transpose函数处理。(你问我为什么?我说:母鸡呀。因为dnn.blobFromImage改变了原图的维度)。下面是对np.transpose函数的理解
传送门
下面我们来显示经过dnn.blobFromImage处理后的图像
import cv2 from cv2 import dnn import numpy as np import matplotlib.pyplot as plt img = cv2.imread("lena.png") print("原图像大小: ", img.shape) Blob = cv2.dnn.blobFromImage(img, scalefactor=1.0 / 255, size=(271, 271), mean=(0, 0, 0), swapRB=False, crop=False) print("blob处理后的: ", Blob.shape) out_put = np.transpose(Blob[0], (1, 2, 0)) print("transpose处理后的: ", out_put.shape) cv2.imshow('original',img) cv2.imshow('outblob',out_put) cv2.waitKey(0)
当然blobFromImage函数也可以对批量的图片进行处理,只需在blobFromImage函数后加上s,blobFromImages。用法类似,后面后面会写到它的用法
对检测的到的boxes和对应的scores进行NMS(非极大值抑制)处理
NMSBoxes(bboxes, scores, score_threshold, nms_threshold, eta, top_k)
参数 | 解释 |
---|---|
bboxes | 待处理的边界框 bounding boxes |
scores | 对于于待处理边界框的 scores |
score_threshold | 用于过滤 boxes 的 score 阈值 |
nms_threshold | NMS 用到的阈值 |
eta | 自适应阈值公式中的相关系数 |
top_k | 如果 top_k>0,则保留最多 top_k 个边界框索引值. |
下面是使用dnn模块的大致流程,可能不怎么清晰明了,但是配合着程序看,还是可以的
其中,dnn.readNetFrom加载权重参数和网络配置文件,这里就不过多介绍了,CSDN里一大堆。还就是你可能会问权重参数和网络配置文件在那搞啊,网上有。但是我发现大都数的都是Caffe的,很少有tensorflow的,还有就是一大堆人也不把文件给你,让你用脚本函数自己转换,而且介绍的方法还不楚。(我就搞不懂了,我他妈要是会,还问你?)。可能有小伙伴会问,能就写一下上面的转换方法吗?不是我不愿写,因为确实没啥用,下面我会直接给出一些权重参数和网络配置文件,小伙伴们直接调用就行了
还有就是detections=net.forward的返回值需要注意:
detections[0, 0, 1, 1] 为第一个是目标的标签
detections[0, 0, 1, 2] 为第一个是目标的置信度
detections[0, 0, 1, 3:7] 为第一个目标的在图片中的位置,起点的 x y坐标
下面我们将分别使用tensorflow和Caffe来完成目标的识别
下面可以使用两个模型的权重参数和网络配置文件,我只使用来其中一个,小伙伴们需修改readNetFromTensorflow()里面的参数,还有inWidth和inHeight的大小。模型一要改为640x640,模型二要改为300x300
模型一:
ssd_mobilenet_v1_fpn_shared_box_predictor_640x640_coco14
提取码:1f6r
模型二:
ssd_mobilenet_v2_coco_300x300
提取码:bek6
PS:上面这两个模型并非只能识别人脸,它可以识别80个类(就是精度低了点)
import cv2 from cv2 import dnn net = cv2.dnn.readNetFromTensorflow('frozen_inference_graph1.pb','graph1.pbtxt') inWidth = 640#因为训练时的图片为该大小 inHeight = 640# confThreshold = 0.5 CLASSES = ['person','bicycle','car','motorbike','aeroplane','bus','train','truck','boat','traffic light','fire hydrant', 'stop sign','parking meter','bench','bird','cat','dog','horse','sheep','cow','elephant','bear','zebra', 'giraffe','backpack','umbrella','handbag','tie','suitcase','frisbee','skis','snowboard','sports ball', 'kite','baseball bat','baseball glove','skateboard','surfboard','tennis racket','bottle','wine glass', 'cup','fork','knife','spoon','bowl','banana','apple','sandwich','orange','broccoli','carrot','hot dog', 'pizza','donut','cake','chair','sofa','potted plant','bed','dining table','toilet','tvmonitor', 'laptop', 'mouse','remote','keyboard','cell phone','microwave','oven','toaster','sink','refrigerator','book','clock', 'vase','scissors','teddy bear','hair drier','toothbrush'] frame = cv2.imread('lena.png') net.setInput(dnn.blobFromImage(frame, 1.0, (inWidth, inHeight), (104.0, 177.0, 123.0), False, False)) detections = net.forward() for i in range(detections.shape[2]): confidence = detections[0, 0, i, 2] idx = int(detections[0, 0, i, 1]) if confidence > confThreshold: x1 = int(detections[0, 0, i, 3] * frame.shape[1]) y1 = int(detections[0, 0, i, 4] * frame.shape[0]) x2 = int(detections[0, 0, i, 5] * frame.shape[1]) y2 = int(detections[0, 0, i, 6] * frame.shape[0]) label = "{}: {:.2f}%".format(CLASSES[idx-1], confidence * 100)#因为这里的对应好像有问题,idx减1就行了 cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0),3)#原谅色 cv2.putText(frame,label,(x1, y1-10),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0),2)#还是原谅色 cv2.imshow("detections", frame) cv2.waitKey(0) cv2.destroyAllWindows()
下面模型用到的相关文件
提取码:gl6a
下面这个程序基本不是本人写的(写的很棒,所以就copy过来给小伙伴们看看)
import numpy as np import cv2 import os image_types = (".jpg", ".jpeg", ".png", ".bmp", ".tif", ".tiff") def list_images(basePath, contains=None): # return the set of files that are valid return list_files(basePath, validExts=image_types, contains=contains) def list_files(basePath, validExts=None, contains=None): # loop over the directory structure for (rootDir, dirNames, filenames) in os.walk(basePath): # loop over the filenames in the current directory for filename in filenames: # if the contains string is not none and the filename does not contain # the supplied string, then ignore the file if contains is not None and filename.find(contains) == -1: continue # determine the file extension of the current file ext = filename[filename.rfind("."):].lower() # check to see if the file is an image and should be processed if validExts is None or ext.endswith(validExts): # construct the path to the image and yield it imagePath = os.path.join(rootDir, filename) yield imagePath # 标签文件处理 rows = open("synset_words.txt").read().strip().split("\n") classes = [r[r.find(" ") + 1:].split(",")[0] for r in rows] # Caffe所需配置文件 net = cv2.dnn.readNetFromCaffe("googlenet.prototxt", "googlenet.caffemodel") # 图像路径 imagePaths = sorted(list(list_images("images/"))) # 图像数据预处理 image = cv2.imread(imagePaths[0]) resized = cv2.resize(image, (224, 224)) # image scalefactor size mean swapRB blob = cv2.dnn.blobFromImage(resized, 1, (224, 224), (104, 117, 123)) print("First Blob: {}".format(blob.shape)) # 得到预测结果 net.setInput(blob) preds = net.forward() print(preds[0]) # 排序,取分类可能性最大的 idx = np.argsort(preds[0])[::-1][0] text = "Label: {}, {:.2f}%".format(classes[idx], preds[0][idx] * 100) cv2.putText(image, text, (5, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)#总是原谅色 # 显示 cv2.imshow("Image", image) cv2.waitKey(0) # Batch数据制作 images = [] # 方法一样,数据是一个batch for p in imagePaths[1:]: image = cv2.imread(p) image = cv2.resize(image, (224, 224)) images.append(image) # blobFromImages函数,注意有s blob = cv2.dnn.blobFromImages(images, 1, (224, 224), (104, 117, 123)) print("Second Blob: {}".format(blob.shape)) # 获取预测结果 net.setInput(blob) preds = net.forward() for (i, p) in enumerate(imagePaths[1:]): image = cv2.imread(p) idx = np.argsort(preds[i])[::-1][0] text = "Label: {}, {:.2f}%".format(classes[idx], preds[i][idx] * 100) cv2.putText(image, text, (5, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)#除了原谅色,还是原谅色 cv2.imshow("Image", image) cv2.waitKey(0)
怕你们程序跑不起来,下面我把所有的文件包括程序打包了一下
传送门
提取码:scfw
模型文件传送门
提取码:dmn0
import cv2 net= cv2.dnn.readNetFromCaffe('deploy.prototxt','res10_300x300_ssd_iter_140000.caffemodel') threshold = 0.87 #加载图片 img = cv2. imread( 'lena.png') frameHeight = img .shape[0] frameWidth = img . shape[1] #进行必要的预处理工作 blob = cv2.dnn.blobFromImage(img, 1.0,(300,300) , [104,117, 123],False, False) #设置网络输入 net.setInput (blob) detections = net. forward() for i in range (detections.shape[2]): confidence = detections[0, 0,i, 2] #与阈值做对比,同一个人脸该过程会进行多次 if confidence > threshold: x1 = int (detections[0, 0, i, 3] * frameWidth) y1 = int (detections[0, 0, i, 4] * frameHeight) x2 = int (detections[0, 0, i, 5] * frameWidth) y2 = int (detections[0, 0, i, 6] * frameHeight) #绘制矩形 cv2. rectangle(img,(x1,y1),(x2,y2),(0,255,0),2)#原谅色 label = "{}: {:.2f}%".format('face', confidence * 100) cv2.putText(img, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)#原谅色 #保存输出 cv2.imshow('out_put',img) cv2.waitKey(0)
就这精度,是不是杠杠的,即使对面部有遮挡,也可以很好的识别。小伙伴们快试试吧
学习opencv有很多的方法,我的建议是你可以加一些群,可以充分利用B站,CSDN,和百度。
在我的博客中,我不会讲解opencv的算法实现(当然我也不太会),我只会讲解一些函数的调用,不理解就多改一些参数,多尝试尝试,慢慢你就理解来。相信你总有一天可以说opencv不过“Ctrl+C,Crtl+V”
如果有什么错误的地方,还请大家批评指正,最后,希望小伙伴们都能有所收获。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。