当前位置:   article > 正文

opencv-python 小白笔记(18)_dnn模块

dnn模块


今天将介绍opencv dnn模块的使用,OpenCV中的深度学习模块(DNN)只提供了推理功能,不涉及模型的训练,支持多种深度学习框架,比如TensorFlow,Caffe,Torch和Darknet等等。说到这里,你应该懂了(深度学习了不起啊?抱歉深度学习真的了不起),有了它我们就可以做很多的事情。

下面来介绍dnn模块的一些函数

(一)dnn.blobFromImage

dnn.blobFromImage,这是一个图像与处理函数,对你输入进来图像进行预处理
blobFromImage(image, scalefactor, size, mean, swapRB, crop, ddepth)

参数解释
imagecv2.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)



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

在这里插入图片描述
当然blobFromImage函数也可以对批量的图片进行处理,只需在blobFromImage函数后加上s,blobFromImages。用法类似,后面后面会写到它的用法

(二)dnn.NMSBoxes

对检测的到的boxes和对应的scores进行NMS(非极大值抑制)处理

NMSBoxes(bboxes, scores, score_threshold, nms_threshold, eta, top_k)

参数解释
bboxes待处理的边界框 bounding boxes
scores对于于待处理边界框的 scores
score_threshold用于过滤 boxes 的 score 阈值
nms_thresholdNMS 用到的阈值
eta自适应阈值公式中的相关系数
top_k如果 top_k>0,则保留最多 top_k 个边界框索引值.

(三)使用流程

下面是使用dnn模块的大致流程,可能不怎么清晰明了,但是配合着程序看,还是可以的

dnn.readNetFrom
待识别图像
dnn.blobFromImage
net.setInput
net.forward

其中,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来完成目标的识别

(四)tensorflow的物体识别

下面可以使用两个模型的权重参数和网络配置文件,我只使用来其中一个,小伙伴们需修改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()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

在这里插入图片描述

(五)Caffe物体分类

下面模型用到的相关文件
提取码: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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89

在这里插入图片描述

怕你们程序跑不起来,下面我把所有的文件包括程序打包了一下
传送门
提取码:scfw

(六)Caffe人脸检测

模型文件传送门
提取码: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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

在这里插入图片描述
就这精度,是不是杠杠的,即使对面部有遮挡,也可以很好的识别。小伙伴们快试试吧

(七)结语

学习opencv有很多的方法,我的建议是你可以加一些群,可以充分利用B站,CSDN,和百度。

在我的博客中,我不会讲解opencv的算法实现(当然我也不太会),我只会讲解一些函数的调用,不理解就多改一些参数,多尝试尝试,慢慢你就理解来。相信你总有一天可以说opencv不过“Ctrl+C,Crtl+V”

如果有什么错误的地方,还请大家批评指正,最后,希望小伙伴们都能有所收获。
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/926843
推荐阅读
相关标签
  

闽ICP备14008679号