前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从头开始在20行代码中查找面部边缘

从头开始在20行代码中查找面部边缘

作者头像
代码医生工作室
发布2019-09-10 15:20:30
8870
发布2019-09-10 15:20:30
举报
文章被收录于专栏:相约机器人相约机器人

正在阅读一本机器学习书,并了解到边缘是机器的重要特征输入,用于了解图片中是否有物体,在这种情况下是面部。看看左边只有边缘的图,可以很容易地说出它是人眼所面孔的,不是吗?这有助于机器以同样的方式。

最初认为寻找边缘本身需要一些“人工智能”。但是记得Python PIL库有find_edges过滤器,它肯定不是机器学习功能。然后开始考虑如何找到边缘并最终找到一种非常简单的方法,只需要从头开始构建大约20行Python代码。

逻辑

逻辑非常简单如下。

  • 从上到下,从左到右扫描所有像素
  • 如果像素与右侧或底部的相邻像素非常不同,请将其标记为边缘。

履行

用Python代码实现了这个,但算法本身与语言无关。

以下是需要的库:

代码语言:javascript
复制
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import math

如果是Python 新手,请先安装Python3,然后使用pip安装所需的库。

代码语言:javascript
复制
pip install -U Pillow numpy matplotlib

首先,将图像读取为2D像素阵列。每个像素是3个值的数组[红色,绿色,蓝色],并且每个颜色值是0到255,例如像素值[0,0,0]是黑色。

代码语言:javascript
复制
filename = 'old.jpg'
im = Image.open(filename)
im_array = np.asarray(im)

如果图像太大,可以先调整图像大小。

代码语言:javascript
复制
n = 2 # resize times
im = im.resize( (int(im.size[0]/n), int(im.size[1]/n)) )

其次,定义了一个函数来测量两个像素之间的差异。使用像素值之间的平方差之和的平方根。

代码语言:javascript
复制
# square root difference between two pixels.
def sqrt_diff(a,b):    
    return math.sqrt( sum((int(a[i])-int(b[i]))**2 for i in range(3)) /3 )

例如,黑色像素A为[0,0,0],白色像素B为[255,255,255],因此A和B之间的平方根差异为:

sqrt(([255–0]**2 + [255–0]**2 + [255–0]**2)/3) = sqrt(255**2) = 255

注意:x ** 2表示x * x。

这里有一个技巧。需要首先将像素值转换为int类型,即int(a[i])减法,因为像素值是ubyte [0-255],减法可能会变为负值并导致类型溢出问题。

在平方根之前将和除以3,因此理解像素差异更直观。它变得像三个颜色值的平均差异。

然后从上到下,从左到右迭代图像阵列。如果像素与其右侧或底部相邻像素之间的平方根差异大于预定义阈值,请将其标记为边缘像素并将其设置为黑色[0,0,0],否则将其设置为白色[255,255,255] ]为背景。

代码语言:javascript
复制
diff_threshold = 10
new_array = np.copy(im_array)
for row in range(im_array.shape[0]-1):
    for col in range(im_array.shape[1]-1):
        # change an edge pixel to black if it is much different from neighbours (right and below)
        # otherwise change it to white as background
        if ( sqrt_diff(im_array[row,col],im_array[row,col+1]) > diff_threshold
            or sqrt_diff(im_array[row,col],im_array[row+1,col]) > diff_threshold):
            new_array[row,col] = [0,0,0] # black
        else:
            new_array[row,col] = [255,255,255] # white

可以diff_threshold为图像微调阈值。10是我用来创建上面图像的值。增加更少边缘的阈值。例如,通过将其增加到20,得到了如下的新图像。

最后,使用matplotlib将新的边缘图像保存到本地。

代码语言:javascript
复制
plt.imshow(new_array)
plt.savefig('new.jpg')

如果要在弹出窗口中显示新图像,请改用以下代码。

代码语言:javascript
复制
plt.imshow(new_array)
plt.show()

可以在此处找到合并的完整代码。

https://gist.github.com/peterjpxie/01595d4beb04e39ed97e6937d4424e7f

笔记

请注意,此算法并非特定于面部检测。它可以找到所有图像的边缘。亲自尝试一下。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 相约机器人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档