基于Matlab制作一个不良图片检测系统

目录
  • 不良图片检测部分
    • part.0 图片导入
    • part.1 检查是否为肤色
    • part.2 皮肤区域标记
    • part.3 通过皮肤区域特点判定是否为不良图片
    • 完整代码
  • 批量处理部分

不良图片检测部分

看到博主码猴小明用python PIL库制作了一个不良图片识别系统,手痒,想用MATLAB也试试,毕竟矩阵运算也算是MATLAB的强项了,使用MATLAB写可比用python写简洁太多了,总体流程如下:

  • 检查各个像素是否为肤色
  • 将相邻的肤色像素归为一个皮肤区域,得到若干个皮肤区域,并剔除像素数量极少的皮肤区域
  • 通过皮肤区域特点判定是否为不良图片

part.0 图片导入

imread读取图片后需要double一下,因为uint8格式的图片数据会自动取整,没法保留小数。

% 读取图片
if nargin<1
    path='test.jpg';
end
picMat=imread(path);
picMat=double(picMat);

本文使用的图片如下:

part.1 检查是否为肤色

这里懒得再去找了,直接使用大佬文中的判定条件,满足以下条件的将其判定为肤色:

  • RGB颜色模式第一种:r > 95 and g > 40 and g < 100 and b > 20 and max([r, g, b]) - min([r, g, b]) > 15 and abs(r - g) > 15 and r > g and r > b
  • RGB颜色模式第二种:nr = r / (r + g + b), ng = g / (r + g + b), nb = b / (r +g + b) ,nr / ng > 1.185 and r * b / (r + g + b) ** 2 > 0.107 and r * g / (r + g + b) ** 2 > 0.112
  • HSV颜色模式:h > 0 and h < 35 and s > 0.23 and s < 0.68
  • YCbCr颜色模式:97.5 <= cb <= 142.5 and 134 <= cr <= 176

网上各种肤色相关公式能找到很多,但是光照亮度不同,灯光颜色不同,肤色不同,各种影响因素太多,不可能100%准确:

% 可调节skinMethod为1/2/3/4
if nargin<2
    skinMethod=3;
end
skinBool=[];
switch skinMethod
    case 1
        % RGB颜色空间检测方法1
        r=picMat(:,:,1);
        g=picMat(:,:,2);
        b=picMat(:,:,3);
        skinBool=(r>95)&(g>40)&(g<100)&(b>20)&(max(picMat,[],3)-min(picMat,[],3)>15)&(abs(r-g)>15)&(r>g)&(r>b);
    case 2
        % RGB颜色空间检测方法2
        nrgb=sum(picMat,3);
        r=picMat(:,:,1);nr=r./nrgb;
        g=picMat(:,:,2);ng=g./nrgb;
        b=picMat(:,:,3);
        skinBool=(nr./ng>1.185)&(r.*b./(nrgb.^2)>0.107)&(r.*g./(nrgb.^2)>0.112);
    case 3
        % HSV颜色空间检测方法
        hsvMat=rgb2hsv(double(picMat)./255);
        h=hsvMat(:,:,1);
        s=hsvMat(:,:,2);
        skinBool=(h>0)&(h<35/180)&(s>0.23)&(s<0.68);
    case 4
        % YCbCr颜色空间检测方法
        ycbcrMat=rgb2ycbcr(uint8(picMat));
        cb=ycbcrMat(:,:,2);
        cr=ycbcrMat(:,:,3);
        skinBool=(cb>=97.5)&(cb<=142.5)&(cr>=134)&(cr<=176);
end
figure();
imshow(uint8(skinBool.*255));

可以看出仅对于本图片,HSV及YCbCr颜色空间检测方法相对较好:

part.2 皮肤区域标记

% 删除面积过小的区域
skinBool=bwareaopen(skinBool,50);

% 获取每一个连通区域(皮肤区域)
skinLabel=bwlabel(skinBool);
skinLabel=sort(skinLabel(:))';
skinLabel(skinLabel==0)=[];

需要注意的是,此时skinLabel标签形式为:

1 1 1 1 2 2 2 3 3 3 3 3 3 4 4 4... ...

假如,1有4个说明被标记为1的区域面积为4,对该序列进行逐项做差能找出每个数值标签第一次出现的位置:

0 0 0 1 0 0 1 0 0 0 0 0 1 0 0... ...

例如2第一次出现在4+1=5的位置,3第一次出现在7+1=8的位置,那么2便一共出现过8-5=3次,那么找到每个数字首次出现位置并再次做差即可获取每种标签出现次数(面积),此方法舍去了for循环,使用向量化编程有了更快的速度:

Lpos=find([diff(skinLabel),1]);
Larea=diff([0,Lpos]);

Larea即为每个区域面积大小。

part.3 通过皮肤区域特点判定是否为不良图片

我们定义非色情图片的判定规则如下(满足任意一个判断为真):

  • 皮肤区域的个数小于3个
  • 皮肤区域的像素与图像所有像素的比值小于15%
  • 最大皮肤区域小于总皮肤面积的45%
  • 皮肤区域数量超过60个
% 皮肤区域的个数小于3个
flag1=length(Larea)<3;
% 皮肤区域的像素与图像所有像素的比值小于15%
flag2=sum(Larea)/numel(picMat(:,:,1))<0.15;
% 最大皮肤区域小于总皮肤面积的45%
flag3=max(Larea)/sum(Larea)<0.45;
% 皮肤区域数量超过60个
flag4=length(Larea)>60;

% 满足任意一项输出否
isBlue=~any([flag1,flag2,flag3,flag4]);

本文实例图片计算结果为否,即非不良图片

完整代码

总共只有短短七十行!:

function isBlue=blueDetect(path,skinMethod)
% 调用方式:
% blueDetect(test.jpg)
% 返回值isBlue为逻辑值true/false

% 读取图片
if nargin<1
    path='test.jpg';
end
picMat=imread(path);
picMat=double(picMat);
%% ========================================================================
% 使用其他皮肤检测方法
% 可调节skinMethod为1/2/3/4
if nargin<2
    skinMethod=3;
end
skinBool=[];
switch skinMethod
    case 1
        % RGB颜色空间检测方法1
        r=picMat(:,:,1);
        g=picMat(:,:,2);
        b=picMat(:,:,3);
        skinBool=(r>95)&(g>40)&(g<100)&(b>20)&(max(picMat,[],3)-min(picMat,[],3)>15)&(abs(r-g)>15)&(r>g)&(r>b);
    case 2
        % RGB颜色空间检测方法2
        nrgb=sum(picMat,3);
        r=picMat(:,:,1);nr=r./nrgb;
        g=picMat(:,:,2);ng=g./nrgb;
        b=picMat(:,:,3);
        skinBool=(nr./ng>1.185)&(r.*b./(nrgb.^2)>0.107)&(r.*g./(nrgb.^2)>0.112);
    case 3
        % HSV颜色空间检测方法
        hsvMat=rgb2hsv(double(picMat)./255);
        h=hsvMat(:,:,1);
        s=hsvMat(:,:,2);
        skinBool=(h>0)&(h<35/180)&(s>0.23)&(s<0.68);
    case 4
        % YCbCr颜色空间检测方法
        ycbcrMat=rgb2ycbcr(uint8(picMat));
        cb=ycbcrMat(:,:,2);
        cr=ycbcrMat(:,:,3);
        skinBool=(cb>=97.5)&(cb<=142.5)&(cr>=134)&(cr<=176);
end
figure();
imshow(uint8(skinBool.*255));
%% ========================================================================
% 删除面积过小的区域
skinBool=bwareaopen(skinBool,50);

% 获取每一个连通区域(皮肤区域)
skinLabel=bwlabel(skinBool);
skinLabel=sort(skinLabel(:))';
skinLabel(skinLabel==0)=[];

% 此时skinLabel标签形式为:
% 1 1 1 1 2 2 2 3 3 3 3 3 3 4 4 4... ...
% 假如,1有4个说明被标记为1的区域面积为4
% 对该序列进行逐项做差能找出每个数值标签第一次出现的位置:
% 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0... ...
% 进而可以获取每种标签所含点数(面积)
% 此方法舍去了for循环使用向量化编程有了更快的速度:
Lpos=find([diff(skinLabel),1]);
Larea=diff([0,Lpos]);

% 皮肤区域的个数小于3个
flag1=length(Larea)<3;
% 皮肤区域的像素与图像所有像素的比值小于15%
flag2=sum(Larea)/numel(picMat(:,:,1))<0.15;
% 最大皮肤区域小于总皮肤面积的45%
flag3=max(Larea)/sum(Larea)<0.45;
% 皮肤区域数量超过60个
flag4=length(Larea)>60;

% 满足任意一项输出否
isBlue=~any([flag1,flag2,flag3,flag4]);
end

批量处理部分

那么我们能不能写一段代码,调用咱前面写的函数,检测文件夹A内的全部图片,并将不良图片保存到B文件夹方便我们扔进回收箱,将正常图片保存在C文件夹方便观看呢?非常简单:

oriPath='.\A\';% 文件夹名称

BPath='.\B\'; % 放置不良图片的路径
nBPath='.\C\';% 放置正常图片的路径

% 若路径下不存在文件夹则创建文件夹
if ~exist(BPath,'dir')
    mkdir(BPath)
end
if ~exist(nBPath,'dir')
    mkdir(nBPath)
end

files=dir(fullfile(oriPath,'*.jpg')); 
picNum=size(files,1);

%遍历路径下每一幅图像
for i=1:picNum
   fileName=strcat(oriPath,files(i).name); 
   isBlue=blueDetect(fileName,3);
   if isBlue
       copyfile(fileName,strcat(BPath,files(i).name));
   else
       copyfile(fileName,strcat(nBPath,files(i).name));
   end
end

那么我们来看看不良图片文件夹的分类效果?:

哈哈哈哈事实证明了解检测原理后构造一张符合条件的图实在是太容易,这种干扰情况过多的判断环境还是得整机器学习。

以上就是基于Matlab制作一个不良图片检测系统的详细内容,更多关于Matlab不良图片检测系统的资料请关注我们其它相关文章!

(0)

相关推荐

  • 详解如何从Matlab中导出清晰的结果图片

    目录 如何从Matlab中导出清晰的结果图片 不清晰的原因 解决办法 原因1的解决办法 原因2的解决办法 总结 如何从Matlab中导出清晰的结果图片 写论文和报告都需要放结果图.但是保存图像的方法不当,保存图片放大缩小都不清晰. 这样: 下面介绍出现不清晰的可能原因,以及可参考的解决办法. 不清晰的原因 保存的时候格式没有选好 图片的文字样式与保存的格式不对应 解决办法 原因1的解决办法   不建议的做法 建议的做法 存储格式 “.png”,“.jpg” “.emf” 原因2的解决办法 步骤一

  • Matlab实现图像边缘检测

    为了在一幅图像 f 的(x,y)位置寻找边缘的强度和方向,所选择的工具就是梯度,梯度使用向量来表示: 该向量指出了图像 f 在位置(x,y)处的最大变化率的方向,梯度向量的大小表示为: 它是梯度向量方向变化率的值. 梯度向量的方向表示为: 梯度算子 roberts算子: sobel算子: prewitt算子: Matlab实现 function output = my_edge(input_img,method) if size(input_img,3)==3 input_img=rgb2gra

  • Matlab 数字图像的滤波及边缘检测

    目录 一.图像滤波 1.1 线性滤波器 1.1.1 均值滤波 1.1.2 高斯滤波 1.2 非线性滤波器 1.2.1 中值滤波器 1.2.2 双边滤波器 1.3 滤波器的 Matlab 代码实现 二.图像边缘检测 2.1 一阶边缘检测算子 2.1.1 Sobel 算子 2.1.2 Canny 算子 2.2 二阶边缘检测算子 2.2.1 拉普拉斯算子 2.3 边缘检测的 Matlab 代码实现 2.4 边缘检测算法总结 三.参考资料 一.图像滤波 图像滤波的主要目的就是在尽量保留图像细节特征的条件

  • Matlab处理图像后实现简单的人脸检测

    1.人脸检测原理框图 整体思路是寻找图片中最大的连通域,将其认定为人脸. 第一个环节均值滤波,是为了减弱图像的相关细节部分,以免毛刺影响后期连通域的形成,二值化方便形态学处理,减少运算量.考虑到人脸有黑人和白人黄种人,黑人肤色较深,在二值化之后面部区域不容易形成较大的连通域,如果采取形态学边界提取的办法,就可以避免这个问题,形态学边界提取,只要结构元素够大,也可以形成较大的封闭连通域. 然后就是纵向闭合操作,这一步我选择采用竖向长条状的结构元素进行闭合运算,因为人的脸部和颈部以及头发和衣物等等都

  • 详解基于Matlab的空心散点检测

    目录 问题描述 过程展示 图像导入 依据RGB值图像二值化 图像腐蚀 图像边缘清理 联通区域查找与坐标均值计算 圈查找 完整代码 其它形状空心散点检测 问题描述 有一张这样的图片,如何提取里面的红色圈圈坐标,并且连接这些坐标形成两个封闭的环路? 过程展示 图像导入 oriPic=imread('test1.png'); subplot(2,2,1) imshow(oriPic) 依据RGB值图像二值化 原理就是图中颜色种类比较少,只有红黑白,而红色和白色都是R通道数值较大,因此我们可以利用这一点

  • 利用Matlab提取图片曲线

    目录 行文动机 图像的读入与裁剪 颜色拾取 颜色转换与色差计算 分离曲线 二值化,提取数据 数据点分类与排序 后话 利用 MATLAB 提取图片曲线 给你一张图片,如何提取里面曲线的数据,从而利用这些数据进行图像重绘.加工处理.测距.拟合得到函数表达式等操作呢? 行文动机 前段时间,有个朋友问了我一个问题,大概意思就是要给图像的流线测距离,在我的印象里面,MATLAB 是似乎没有这种直接的功能的. 那么换个角度来理解一下这个问题,如果给你一张图像,如何提取里面点的数据?其实,有了曲线的数据,后面

  • 基于Matlab制作一个不良图片检测系统

    目录 不良图片检测部分 part.0 图片导入 part.1 检查是否为肤色 part.2 皮肤区域标记 part.3 通过皮肤区域特点判定是否为不良图片 完整代码 批量处理部分 不良图片检测部分 看到博主码猴小明用python PIL库制作了一个不良图片识别系统,手痒,想用MATLAB也试试,毕竟矩阵运算也算是MATLAB的强项了,使用MATLAB写可比用python写简洁太多了,总体流程如下: 检查各个像素是否为肤色 将相邻的肤色像素归为一个皮肤区域,得到若干个皮肤区域,并剔除像素数量极少的

  • 基于Matlab制作一个数独求解器

    目录 1.完整效果 2.数独求解(错误示范) 3.数独求解(升维) 4.数字识别 5.GUI / APP 讲解一个完整的小项目,顺便说明如何使用整数规划求解数独. 1.完整效果 2.数独求解(错误示范) 首先我们先尝试如果只满足行.列.3x3块加和均为45的等式约束是否有效.即约束为: 每行和为45: 每列和为45: 每个3x3块和为45: 其中对此编写如下代码: sudokuMat=[1 0 5 0 2 0 0 0 0 0 0 0 7 4 3 0 0 5 3 0 7 0 0 0 0 0 9 0

  • 基于PyQT5制作一个敏感词检测工具

    设计思路:根据敏感词库文件筛选,查看输入的文本中是否包含敏感词汇.从而过滤出相关的敏感词. 导入应用相关的模块. import os import logging import sys 导入UI界面相关的模块. from PyQt5.QtWidgets import QApplication,QWidget,QVBoxLayout,QTextEdit,QGridLayout,QLineEdit,QPushButton,QFileDialog from PyQt5.QtGui import QIc

  • 详解基于electron制作一个node压缩图片的桌面应用

    基于electron制作一个node压缩图片的桌面应用 下载地址:https://github.com/zenoslin/imagemin-electron/releases 项目源码Github:https://github.com/zenoslin/imagemin-electron 准备工作 我们来整理一下我们需要做什么: 压缩图片模块 获取文件路径 桌面应用生成 压缩图片 我们需要使用imagemin这个库来压缩图片,这里我们把这个库封装成压缩模块. const imagemin = r

  • 基于PyQt5制作一个gif动态图片生成器

    这个小工具制作的目的是为了将多张图片组合后生成一张动态的GIF图片.设置界面化的操作,只需要将选中的图片导入最后直接生成动态图片. 导入界面相关的第三方库 from PyQt5.QtWidgets import * from PyQt5.QtGui import * 动态图片处理模块 import imageio 应用操作相关库 import sys import os from datetime import datetime 这是用图片生成器生成的一张GIF图片,大家在生成时尽量选择两张大小

  • 基于PyQT5制作一个课堂点名系统

    刷抖音的时候发现一个老师在用的课堂点名系统.用PyQt5实现了一下同款,导入学生姓名,测试了一下完美运行. 操作效果展示: 完整源代码块还是放在了文章的最后面 使用的时候准备好学生姓名的文件,使用导入数据的按钮直接导入就可以开始点名了.新建一个文本文档,将姓名设置设置好,姓名文件示例如下. 使用系统库或者第三方库都比较常规,这里就不一一介绍了. from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore im

  • 基于Matlab图像处理的公路裂缝检测实现

    目录 一.简介 1案例背景 2理论基础 3程序实现 二.部分源代码 三.运行结果 一.简介 1 案例背景 随着国家对公路建设的大力投入,我国的公路通车总里程己经位居世界前列,这样进一步促进了我国经济建设的发展.随着公路的大量投运,公路日常养护和管理已经成为制约公路运营水平提高的瓶颈,特别是路面状态采集.检测维护等工作更是对传统的公路运维模式提出了挑战.路面裂缝是公路日常养护管理中最常见的路面损坏,也是影响公路状态评估和进行必要的公路维修的重要因素!.一般而言,如果路面裂缝能够在被恶化成坑槽之前得

  • 基于PyQt5制作一个windows通知管理器

    前几天看到一个python框架win10toast,它可以用来做windows的消息通知功能.通过设定通知的间隔时间来实现一些事件通知的功能,比如可以可以提醒一头扎进代码编写过程的我们按时喝水. 界面布局采用的依旧是pyqt5的ui设计,使用界面化直接设置好想要提示的内容和时间就可以给我们定时的发通知了. UI相关的部分的还是这几个常用的组件包. from PyQt5.QtGui import * # UI 界面相关 from PyQt5.QtCore import * # 核心组件包 from

  • 基于Matlab制作一款简单的龙舟小游戏

    效果图: 没找到合适的背景就自己画了个,大家如果有更好看的可以换一下... 步骤 1 创建Axes及图片导入 窗口创建: Mainfig=figure('units','pixels','position',[50 100 760 400],... 'Numbertitle','off','menubar','none','resize','off',... 'name','dragonBoat'); axes('parent',Mainfig,'position',[0 0 1 1],...

随机推荐