毛孔识别

本文仅仅描述如何用opencv完成一个入门级别的毛孔识别,基于python3.7和 opencv 4.3

原图以及识别生成的效果图

一、首先引入需要的包,然后读取需要识别的图片

import cv2
import numpy as np
imageMat = cv2.imread("b.png")

二、选取B通道和均值滤波

选取通道是为了将图片转换为灰度图,以便后续的阀值处理,具体选取BGR哪个根据图片不同而不同;之后均值滤波以降噪,要在失真和去噪效果之间取得平衡,选取合适大小的卷积核

#选取blue通道
blueChannelMat = imageMat[:,:,0]
#均值滤波(滤波窗口越大图像失真越严重即更模糊)
blurMat = cv2.blur(blueChannelMat,(5,5))#5,5表示卷积核大小是5x5

三、阀值分割

阀值分割是将灰度图转换为二值图,这也是关乎识别质量很重要的一步,关键在于阀值大小的选取;图中大于阀值的像素会被设置为最大值(一般为255),小于或等于阀值的像素灰度值会被设置为0

otsu法是一种自动计算阀值的算法,通过如下代码可以获取阀值t和二值图

#动态阀值分割(otsu法)
t,thresMat = cv2.threshold(blurMat,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

但有时otsu的效果并不好,就比如现在这样,阀值明显是偏大了

这时就需要手动设置一个合适的阀值(根据阀值处理的效果不断调整到合适为止),并且将参数从THRESH_BINARY修改为THRESH_BINARY_INV即反向阀值处理,因为我们识别的对象是黑色的毛孔,像素值趋向0,阀值处理后像素会被设置为0,而反向阀值则把毛孔的像素设置为255,为什么这么做后面会说明

t,thresMat = cv2.threshold(blurMat,70,255,cv2.THRESH_BINARY_INV)

看到这里你应该能理解识别是怎么做到的了,其实就是因为黑色的毛孔像素值低,可以通过阀值分割出来,完成了对毛孔和皮肤的区分,图里的白色部分就是分割出的毛孔

四、腐蚀膨胀

腐蚀和膨胀简单是去除那些单独小的噪点和让毛孔边缘更平滑,这里不展开说明;根据图片和毛孔的大小调整卷积核的大小,毛孔小卷积核也要取小点,一般取3x3,5x5,7x7......

下面腐蚀膨胀的处理参考了论文: 《基于计算机视觉的皮肤毛孔识别及精准定位》 - 苏晓朋

#核为矩形5x5腐蚀
k1 = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))#生成形状为矩形5x5的卷积核
x0 = cv2.erode(thresMat, k1) #核为圆形9x9开运算
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(9,9))
x1 = cv2.morphologyEx(thresMat,cv2.MORPH_OPEN,kernel) #9x9椭圆核开闭运算
x1 = cv2.morphologyEx(x1,cv2.MORPH_OPEN,kernel)
x2 = cv2.morphologyEx(x1,cv2.MORPH_CLOSE,kernel)

腐蚀膨胀处理后的效果

五、标识毛孔

这里采用opencv的查找轮廓函数来查找连通区域(即图中的白色区域),然后通过计算每个轮廓的面积来大致计算毛孔面积。前面提到阀值分割时要使用反向阀值分割,是因为opencv查找轮廓是以白色区域为对象,就是只会查找白色区域的轮廓

#计算连通区域面积
#查找图像轮廓,参数分别表示只检测外轮廓,存储所有轮廓点
contours,hierarchy=cv2.findContours(x2,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE) #计算轮廓面积
contoursArea=[]#存储面积的列表
contours_sel=[]#存储符合要求的轮廓
for i in range(len(contours)):
temp = cv2.contourArea(contours[i])
if temp>30:#筛选出面积大于30的轮廓
contoursArea.append(temp)
contours_sel.append(contours[i]) #绘制轮廓,第一个参数是你要绘制轮廓的图,第二个参数是使用的轮廓,
#第一个-1表示绘制所有轮廓,(0,255,0)是绘制使用的颜色,第二个-1表示填充轮廓内部
x2 = cv2.drawContours(imageMat,contours_sel,-1,(0,255,0),-1)
cv2.imshow("b",x2)#显示图像
cv2.waitKey()
cv2.destroyAllWindows()

下图是识别出的轮廓叠加在原图上的结果

六、如何生成mask图

一般我们用于训练神经网络使用的label图是mask图,当然这里的label图还要人工修正,这里只说说如何从查找到的轮廓生成mask图

#先生成一张纯白的图
mask = np.zeros(imageMat.shape,np.uint8)#生成和原图大小一致的黑色图片
t,mask = cv2.threshold(mask,0,255,cv2.THRESH_BINARY_INV)#通过阀值将其反色为白图
#在白图上绘制查找到的轮廓即可
mask = cv2.drawContours(mask,contours_sel,-1,(0,0,0),-1)
cv2.imshow('m',mask)

第一次写博客,经验不足请多多包涵,之后应该会更新如何使用Unet神经网络来分割出毛孔的文章

参考文献

[1] 林绵. 面部皮肤评测系统的设计与实现[D].华南理工大学,2016.

[2] 李立综. OpenCV轻松入门:面向Python[M].电子工业出版社,2019-05-01

[3] 苏晓朋. 基于计算机视觉的皮肤毛孔识别及精准定位[D].华北电力大学(北京),2018.

本文为博主原创文章,未经博主允许禁止转载

声明:本文同步发布于CSDN:https://blog.csdn.net/Misaki____Mei/article/details/107272751

opencv毛孔识别(python实现)的更多相关文章

  1. 人脸检测及识别python实现系列(6)——终篇:从实时视频流识别出“我”

    人脸检测及识别python实现系列(6)——终篇:从实时视频流识别出“我” 终于到了最后一步,激动时刻就要来临了,先平复一下心情,把剩下的代码加上,首先是为Model类增加一个预测函数: #识别人脸 ...

  2. 人脸检测及识别python实现系列(3)——为模型训练准备人脸数据

    人脸检测及识别python实现系列(3)——为模型训练准备人脸数据 机器学习最本质的地方就是基于海量数据统计的学习,说白了,机器学习其实就是在模拟人类儿童的学习行为.举一个简单的例子,成年人并没有主动 ...

  3. 人脸检测及识别python实现系列(1)——配置、获取实时视频流

    人脸检测及识别python实现系列(1)——配置.获取实时视频流 1. 前言 今天用多半天的时间把QQ空间里的几篇年前的旧文搬到了这里,算是完成了博客搬家.QQ空间里还剩下一些记录自己数学学习路线的学 ...

  4. OpenCV.物体识别

    1.度娘:“OpenCV 物体识别” 1.1.opencv实时识别指定物体 - 诺花雨的博客 - CSDN博客.html(https://blog.csdn.net/qq_27063119/artic ...

  5. opencv +数字识别

    现在很多场景需要使用的数字识别,比如银行卡识别,以及车牌识别等,在AI领域有很多图像识别算法,大多是居于opencv 或者谷歌开源的tesseract 识别. 由于公司业务需要,需要开发一个客户端程序 ...

  6. opencv人脸识别代码

    opencv人脸识别C++代码 /* * Copyright (c) 2011,2012. Philipp Wagner <bytefish[at]gmx[dot]de>. * Relea ...

  7. 人脸检测及识别python实现系列(2)——识别出人脸

    人脸检测及识别python实现系列(2)——识别出人脸 http://www.cnblogs.com/neo-T/p/6430583.html

  8. OpenCV人脸识别的原理 .

    OpenCV人脸识别的原理 . 在之前讲到的人脸测试后,提取出人脸来,并且保存下来,以供训练或识别是用,提取人脸的代码如下: void GetImageRect(IplImage* orgImage, ...

  9. 人脸检测及识别python实现系列(5)——利用keras库训练人脸识别模型

    人脸检测及识别python实现系列(5)——利用keras库训练人脸识别模型 经过前面稍显罗嗦的准备工作,现在,我们终于可以尝试训练我们自己的卷积神经网络模型了.CNN擅长图像处理,keras库的te ...

随机推荐

  1. 动作函数-web_url

    web_url("WebTours", "URL=http://127.0.0.1:1080/WebTours/", "TargetFrame=&qu ...

  2. OO第三单元——JML之破分大法

    一.Jml总结及应用工具链 总的来说,jml就是对java程序进行规格化设计的一种表示语言,其中最核心的就是规格化,将代码要实现的功能和各项要求与约束不是通过自然语言,而是通过严密的逻辑语言来表达,这 ...

  3. selenium自动化操作

    在前面爬虫的相关介绍中,我们介绍了如何抓取静态页面信息.但是,在实际的网页浏览过程中,我们可能会经常碰到各种需要进行交互的操作,典型的如输入信息.点击按钮之类. 对于这种场景,之前的静态页面操作方式已 ...

  4. GitHub 热点速览 Vol.25:距离优雅编程你差个它

    作者:HelloGitHub-小鱼干 摘要:如何优雅地夸一个程序员呢?vscode-rainbow-fart 作为一个彩虹屁的项目,深得程序员心,能在你编程时疯狂称赞你的除了你自己,还有它.除了鼓励之 ...

  5. 利用c++中的设计灵感,既要学BIM分类信息表,借助GIS完成环境搭建改善

    我,一个平平无奇的城市规划专业(建筑专业.路桥专业)大学生,还有一年要毕业,很担心工作以后受到社会的毒打,遂问导师和学长,我要自学点什么技能和软件? 学长A:CAD,SketchUp,PS我都很熟练了 ...

  6. 流媒体学习计划表——pr

    参考教程 视频:b站oeasy 书籍:<adobe premiere pro cc 2018经典教程> 学习教训 一定要多做--实践是检验真理的唯一标准 书籍补充理论知识,视频讲究实操(理 ...

  7. Java WebService(实战) 简单实例

    一.准备工作(以下为本实例使用工具) 1.MyEclipse10.7.1 2.JDK 1.6.0_22 二.创建服务端 1.创建[Web Service Project],命名为[TheService ...

  8. Illegal reflective access by org.apache.hadoop.security.authentication.util.KerberosUtil

    在使用Java API操作HBase时抛出如下异常: Illegal reflective access by org.apache.hadoop.security.authentication.ut ...

  9. 使用docker创建rocketMQ容器

    一.rocketMQ安装 (一)安装NameSrv 1.创建nameSrv数据挂载文件夹 mkdir -p /usr/data/rocketMQ/data/namesrv/logs mkdir -p ...

  10. git和github入门指南(3.1)

    3.远程管理 3.1.远程仓库相关命令 1.查看远程仓库名字,这里以github为例 git remote 上面命令执行后会得到:origin,这样一个名字,这个名字是我们克隆的时候默认设置好的 如果 ...