对比python学julia(第四章:人工智能)--(第一节)OpenCV编程初步(2)

1.4.        人脸检测

  人脸检测的任务是从一个图像中寻找出人脸所在的位置和大小。0penCV提供了级联分类器(CascadeClassifier) 和人脸特征数据,只用少量代码就能实现人脸检测功能。

  在本小节中,将学习编写几个简单的人脸检测程序,以此掌握在0penCV中操作图像、视频和摄像头的方法。

  1.准备工作

  在本地磁盘新建目录“BaseOpenCV”作为项目目录,从原书提供的“资源包/第32课/”中把“人脸检测”文件夹中的子目录和文件拷贝到新建的项目目录中,这是准备好的用于检测的人脸图像、视频和人脸(正脸)特征数据文件。 下面编写的人脸检测程序也存放在这个文件夹中。

  2.检测图像中的人脸

在VSCode环境中,打开项目目录,新建一个空白源文件 ,以detect_image.jl作为文件名保存到“BaseOpenCV”中,然后编写程序检测图像中的人脸(正脸),具体过程如下。

  (1) 导入 cv2 库。

using PyCall

cv2=pyimport("cv2")

  (2) 从文件中加载一个含有人脸的图像,并转换得到一个灰度图像。

img = cv2.imread("images/face1.jpg")

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

  说明:OpenCV提供的cvtColor()方法是用于转换图像的色彩空间,使用cv2.OLOR_BGR2GRAY参数可以将一个彩色图像转换为灰度图像。

  (3) 利用人脸特征数据创建一个人脸检测器(CascadeClassifier类的实例),然后调用该实例的detectMultiScale()方法检测图像中的人脸区域,将检测结果返回给变量faces。

file = "haarcascade_frontalface_default.xml"

face_cascade = cv2.CascadeClassifier(file)

faces = face_cascade.detectMultiScale(gray, 1.3, 5)

  说明:在调用detectMultiScale( )方法的参数中,第1个参数是一个灰度图像;第2个参数表示在前后两次相继的扫描中,搜索窗口的比例系数(默认为l.1,即每次搜索窗口依次扩大1的0;第3个参数表示构成检测目标的相邻矩形的最小个数(默认为3个)。

  (4) 在检测图像中的每一个人脸区域画上矩形框。

#Julia数组是列主数组,而cv需要行主数组。

#反转维度,然后使用PyReverseDims数组

rimg = permutedims(img, ndims(img):-1:1)

pyimg = PyReverseDims(rimg)

for i in 1:size(faces)[1]

    x=faces[i,1]

    y=faces[i,2]

    w=faces[i,3]

    h=faces[i,4]

    cv2.rectangle(pyimg, (x, y), (x+w, y+h), (255, 0, 0), 3)

end

  说明:检测出的人脸区域是一个矩形,由左上角座标(x,y)和矩形的宽度w和高度h来确定。利用cv2.rectangle()方法可以在图像上画出一个矩形,该方法的第1个参数是图像,第2个参数是矩形的左上角座标(x,y),第3个参数是矩形的右下角座标(x+w,y+h),第4个参数是线条的颜色,第5个参数是线条的宽度。

  注:以上代码中的for循环,python代码是这样写的

for (x, y, w, h) in faces:

    cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 3)

  为什么这样遍历faces中的元素?我们首先看一下faces是什么。通过type(faces)方法,我们可以获得faces的类型是”numpy.ndarray“, 这个ndarray(全称The N-dimensional array)是存储着相同类型和大小的元素的多维数组,再通过faces.shape,可知其是一个(3,4)的数组,for (x, y, w, h) in faces的结果,是遍历faces的每行,并将每行的4个元素值分别赋值给x, y, w, h四个变量。

  我们再来看在julia中,faces是什么。通过前面我们提到过typeof(faces),我们可以获得faces的类型是“Matrix{Int32} “,是一个元素为Int32类型的矩阵。但是julia的矩阵是列主存储的,因此无法默认以 “行“遍历的方式访问,因此人脸检测的juli代码中,对这一处进行了改写。其中size()方法与python的shape一样,可以获得数组的真实维度值,而度值是一个元组类型,然后可以循环访问维度值的第一维,即矩阵的”行“,再将每行的元素值赋值给x,y,w,h四个遍历。

  • 拓展知识:

  关于在juia中以循环方式对矩阵元素的访问(也称迭代),这里再做进一步的拓展说明。

     首先我们构造一个3x4的矩阵

julia> m = [10i+j for i=1:3, j=1:4]

3×4 Matrix{Int64}:

 11  12  13  14

 21  22  23  24

 31  32  33  34

    按照人脸检测的代码方式,我们可以这样遍历这个矩阵:

julia> for i=1:size(m)[1]

         x= m[i,1]

    y= m[i,2]

    w= m[i,3]

    h= m[i,4]

         println(x+1," ",y+1," ",w+1," ",h+1)

       end

输出结果:

    12 13 14 15

 22 23 24 25

 32 33 34 35

  当然我们还可以这样写:

julia>  for i=1:size(m)[1]

            x,y,w,h=m[i,1:4]

            println(x+1," ",y+1," ",w+1," ",h+1)

        end

  我们还可以这样写:

julia>  for i=1:size(m,1)

            x,y,w,h=m[i,1:4]

            println(x+1," ",y+1," ",w+1," ",h+1)

        end

  我们还可以这样写:

julia>  for i=1:size(m,1)

            x,y,w,h=m[i,:]

            println(x+1," ",y+1," ",w+1," ",h+1)

        end

  还有更花式的写法:

julia>  for row in eachrow(m)

             x,y,w,h=row

             println(x+1," ",y+1," ",w+1," ",h+1)

        end

  以上各种写法,哪个是性能最好的写法?大家可以研究一下。

  (5) 把标注矩形框后的图像显示到窗口。

cv2.imshow("Image", pyimg)

  (6) 等待用户按下任意按键,之后销毁所有窗口。

cv2.waitKey(0)

cv2.destroyAllWindows()

  至此,人脸检测程序编写完毕。运行程序,结果如图所示 。

wwan

  完整代码下载::https://files.cnblogs.com/files/zjzkiss/face_detect1.rar

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章