词云之matlab实现复杂数字图像背景剔除

为了制作各种好看的词云标签,一张好的背景图片寻找起来并不容易,例如本文所使用的"汗血宝马"的图片,背景不是我所需要的,如何实现对图像的有效分割?去除背景噪声是本文关注的重点。本文拟采用matlab来实现这个简易的功能。
1.本文将对马进行测试
在这里插入图片描述
2.数字图像背景去除最好的方式有以下几种:
a.PhontoShop,使用选择工具即可;
b.最简单的阈值分割理论;(本文的方法),C++,matlab,python都有实现的包可以供调用。
c.背景差分算法;

3.数字图像阈值分割处理的一般化流程

…1.直接读入图片后,做二值化处理,根据数据游标的取值做初步的分割考察,或者使用imhist绘制图像的像素分布直方图来确定分割像素值;
…2.如果直接阈值分割不行,那可以考虑变换颜色空间来看是否便于基于颜色做图像分割;
…3.在变换了颜色空间的图像上,通过数据游标直接选定大致的阈值,后续再手动改进;
…4.分割后的图像常常会有孔洞,此时需要多次使用形态学方法(进行形态学处理:腐蚀和膨胀)来做孔洞填充;
…5.图像拼接的话需要imresize()成相同大小的图片;
…6.知识迁移到人脸识别应用中来,可以框出人脸位置区域(人脸正面照效果较好)

4.分割马的图像并框选出来马

%function:
%       基于颜色的图像分割;
%       定位图片中的马的区域;
%procession:
%       1.直接读入图片后,做二值化处理,根据数据游标的取值做初步的分割考察;
%       2.如果直接阈值分割不行,那需要考虑变换颜色空间来看是否便于图像分割;
%       3.在变换了颜色空间的图像上,通过数据游标直接选定大致的阈值,后续再手动改进;
%       4.分割后的图像常常会有孔洞,此时需要多次使用形态学方法(进行形态学处理:腐蚀和膨胀)来做孔洞填充;
%       5.图像拼接的话需要imresize()成相同大小的图片;
%       6.知识迁移到人脸识别应用中来,可以框出人脸位置区域(适用于人脸正面照)


clear  all;
clc;
close all;
%开始计时
tic
%输入需要识别的图像
[filename,pathname,fi]=uigetfile(...
                    {'*.*', 'all image file (*.*)';...
                     '*.bmp','all image file (*.bmp)';...
                     '*.jpg','all image file (*.jpg)'},...
                     '请选择要识别的图片',...
                     'MultiSelect', 'on');
RGB=imread([pathname filename]); %界面手动选择读入方式
%RGB = imread('D:\Program Files\MATLAB\workspace\timg1.jpg'); %直接路径传入读取方式

figure('name','process'),
subplot(2,2,1),imshow(RGB),title('原始RGB'),

%convert frame from RGB to YCBCR colorspace(转换到YCBCR空间)
YCBCR = rgb2ycbcr(RGB);
whos,
subplot(2,2,2),imshow(YCBCR),title('YCBCR'),
%filter YCBCR image between values and store filtered image to threshold
%matrix(用各个通道的阈值对其进行二值化处理)
%% 通过数据游标直接选定大致的阈值,后续再手动改进
%Y_MIN = 40;  Y_MAX = 160;
%Cb_MIN = 80;   Cb_MAX = 120;
%Cr_MIN = 138;   Cr_MAX = 195;
Y_MIN = 30;  Y_MAX = 215; %到255也可以
Cb_MIN = 65;   Cb_MAX = 135;
Cr_MIN = 138;   Cr_MAX = 195; %已经是最佳,否则会引入背景噪声.
threshold1=roicolor(YCBCR(:,:,1),Y_MIN,Y_MAX)&roicolor(YCBCR(:,:,2),Cb_MIN,Cb_MAX)&roicolor(YCBCR(:,:,3),Cr_MIN,Cr_MAX);
subplot(2,2,3),imshow(threshold1),title('YCBCR二值化'),

%perform morphological operations on thresholded image to eliminate noise
%and emphasize the filtered object(s)(进行形态学处理:腐蚀、膨胀、孔洞填充)
dilateElement=strel('square',13) ;
threshold=imdilate(threshold1, dilateElement);
erodeElement = strel('square', 4) ;
threshold = imerode(threshold,erodeElement);
erodeElement = strel('square', 3) ;
threshold = imerode(threshold,erodeElement);
erodeElement = strel('square', 2) ;
threshold = imerode(threshold,erodeElement);
threshold=imfill(threshold,'holes');
subplot(2,2,4),imshow(threshold),title('形态学处理');
% matlab多行注释
%{
    erodeElement = strel('square', 2) ;
    dilateElement=strel('square',4) ;
    threshold = imerode(threshold,erodeElement);
    threshold = imerode(threshold,erodeElement);
    threshold=imdilate(threshold, dilateElement);
    threshold=imdilate(threshold, dilateElement);
    threshold=imfill(threshold,'holes');
    subplot(2,2,4),imshow(threshold),title('形态学处理'),
 %}

%获取区域的'basic'属性, 'Area', 'Centroid', and 'BoundingBox' 
figure('name','处理结果'),
stats = regionprops(threshold, 'basic');
[C,area_index]=max([stats.Area]);
%定位马的区域
face_locate=[stats(area_index).Centroid(1),stats(area_index).Centroid(2)];
imshow(RGB);title('after'),hold on
text(face_locate(1),face_locate(2)-40,  'face','color','red');
plot(face_locate(1),face_locate(2), 'b*');
rectangle('Position',[stats(area_index).BoundingBox],'LineWidth',2,'LineStyle','--','EdgeColor','r'),
hold off 

%将五张图片拼接成一张完整的图像
RGB= imresize(RGB ,[1800 2307],'nearest')  % 'nearest'最近邻插值(默认),'bilinear'双线性插值,'bicubic'双三次插值
YCBCR= imresize(YCBCR ,[1800 2307],'nearest')  % 'nearest'最近邻插值(默认),'bilinear'双线性插值,'bicubic'双三次插值
threshold1= imresize(threshold1 ,[1800 2307],'nearest') 
threshold= imresize(threshold ,[1800 2307],'nearest') 
figure
imshow([RGB,YCBCR]) %面向对象的思想,将对象也当做最特殊的元素
figure
imshow([threshold1,threshold]) 
t=toc

在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述将马匹抠图抠出来

[filename,pathname,fi]=uigetfile(...
                    {'*.*', 'all image file (*.*)';...
                     '*.bmp','all image file (*.bmp)';...
                     '*.jpg','all image file (*.jpg)'},...
                     '请选择要识别的图片',...
                     'MultiSelect', 'on');
in_image=imread([pathname filename]);
figure(1);imshow(in_image);title('原始图像');%显示原始图像
imshow(in_image(:,:,3));
 BW = im2bw(in_image(:,:,3),0.46); %将图片转为二值图片
 se = strel('disk',1)
 figure(2);imshow(BW);title('去除背景');
 %se=[0 0 0 0 0;0 0 0 0 0;0 0 1 0 0;0 0 0 0 0;0 0 0 0 0]
 %BW = imdilate(BW,se);%imerode
 %figure;imshow(BW);title('去除背景');
 se1=strel('disk',1);%这里是创建一个半径为4的平坦型圆盘结构元素
 BW=imerode(BW,se1);
 figure;imshow(BW); 
 in_image(repmat(BW,[1,1,3])) = 0;
 figure(3);imshow(in_image);title('去除背景');

在这里插入图片描述在这里插入图片描述在这里插入图片描述6.孔洞问题解决
尽管上述代码好像已经可以实现将马匹分割出来,但是孔洞的存在,依然极大的影响了图像的美观!故对上述代码再做些需改进,以达到填补孔洞的目的。

%输入需要识别的图像
[filename,pathname,fi]=uigetfile(...
                    {'*.*', 'all image file (*.*)';...
                     '*.bmp','all image file (*.bmp)';...
                     '*.jpg','all image file (*.jpg)'},...
                     '请选择要识别的图片',...
                     'MultiSelect', 'on');
in_image=imread([pathname filename]);
figure(1);imshow(in_image);title('原始图像1');%显示原始图像
imshow(in_image(:,:,3));
BW = im2bw(in_image(:,:,3),0.46); %将图片转为二值图片
se = strel('disk',2)
figure(2);imshow(BW);title('去除背景1');
se1=strel('disk',7);%这里是创建一个半径为7的平坦型圆盘结构元素,合理调节strel()参数和  使用腐蚀和膨胀的次数就可以很好地进行孔洞的填充。
BW=imerode(BW,se1);
se1=strel('disk',1);
BW=imerode(BW,se1);
BW = imdilate(BW,se);%imerode
figure;imshow(BW); 
in_image(repmat(BW,[1,1,3])) = 0;
figure(3);imshow(in_image);title('去除背景2');

在这里插入图片描述在这里插入图片描述
马对象内部白色不是我们想要的,所以使用腐蚀腐蚀掉黑色区域中的白色像素,效果如下所示:
在这里插入图片描述在这里插入图片描述
在不对黑色区域做处理的情况下,获得的马的分割后的图像:
在这里插入图片描述显然马对象太胖了,应该减肥还原,使用膨胀操作,收缩黑色区域。

%初始化
clc;clear all;
close all;
%开始计时
tic
%输入需要识别的图像
[filename,pathname,fi]=uigetfile(...
                    {'*.*', 'all image file (*.*)';...
                     '*.bmp','all image file (*.bmp)';...
                     '*.jpg','all image file (*.jpg)'},...
                     '请选择要识别的图片',...
                     'MultiSelect', 'on');
in_image=imread([pathname filename]);
figure(1);imshow(in_image);title('原始图像1');%显示原始图像
imshow(in_image(:,:,3));
BW = im2bw(in_image(:,:,3),0.46); %将图片转为二值图片
figure(2);imshow(BW);title('去除背景1');
se1=strel('disk',7);%这里是创建一个半径为7的平坦型圆盘结构元素,合理调节strel()参数和使用腐蚀和膨胀的次数就可以很好地进行孔洞的填充。
BW=imerode(BW,se1);
figure;imshow(BW); 
se1=strel('disk',1);
BW=imerode(BW,se1);
figure;imshow(BW); 
se = strel('disk',9)
BW = imdilate(BW,se);%imerode
figure;imshow(BW); 
in_image(repmat(BW,[1,1,3])) = 0;
figure(3);imshow(in_image);title('去除背景2');
t=toc

黑色区域"膨胀"前:
在这里插入图片描述
黑色区域"膨胀"后:
在这里插入图片描述在这里插入图片描述
还有些不够完美的地方,尾巴的处理跟PS的效果差不多。
使用PS的“快速选择工具”的PS效果图如下:
在这里插入图片描述
6.知识迁移到单个人脸框选

clear  all;
clc;
close all;
%开始计时
tic
%输入需要识别的图像
[filename,pathname,fi]=uigetfile(...
                    {'*.*', 'all image file (*.*)';...
                     '*.bmp','all image file (*.bmp)';...
                     '*.jpg','all image file (*.jpg)'},...
                     '请选择要识别的图片',...
                     'MultiSelect', 'on');
RGB=imread([pathname filename]); %界面手动选择读入方式
%RGB = imread('D:\Program Files\MATLAB\workspace\timg1.jpg'); %直接路径传入读取方式

figure('name','process'),
subplot(2,2,1),imshow(RGB),title('原始RGB'),

%convert frame from RGB to YCBCR colorspace(转换到YCBCR空间)
YCBCR = rgb2ycbcr(RGB);
whos,
subplot(2,2,2),imshow(YCBCR),title('YCBCR'),
%filter YCBCR image between values and store filtered image to threshold
%matrix(用各个通道的阈值对其进行二值化处理)
%% 通过数据游标直接选定大致的阈值,后续再手动改进
%Y_MIN = 40;  Y_MAX = 160;
%Cb_MIN = 80;   Cb_MAX = 120;
%Cr_MIN = 138;   Cr_MAX = 195;
Y_MIN =20;  Y_MAX = 160; 
Cb_MIN = 100;   Cb_MAX = 150;
Cr_MIN = 110;   Cr_MAX = 170; %已经是最佳,否则会引入背景噪声.
threshold1=roicolor(YCBCR(:,:,1),Y_MIN,Y_MAX)&roicolor(YCBCR(:,:,2),Cb_MIN,Cb_MAX)&roicolor(YCBCR(:,:,3),Cr_MIN,Cr_MAX);
subplot(2,2,3),imshow(threshold1),title('YCBCR二值化'),

%perform morphological operations on thresholded image to eliminate noise
%and emphasize the filtered object(s)(进行形态学处理:腐蚀、膨胀、孔洞填充)
dilateElement=strel('square',13) ;
threshold=imdilate(threshold1, dilateElement);
erodeElement = strel('square', 4) ;
threshold = imerode(threshold,erodeElement);
erodeElement = strel('square', 3) ;
threshold = imerode(threshold,erodeElement);
erodeElement = strel('square', 2) ;
threshold = imerode(threshold,erodeElement);
threshold=imfill(threshold,'holes');
subplot(2,2,4),imshow(threshold),title('形态学处理');
% matlab多行注释
%{
    erodeElement = strel('square', 3) ;
    dilateElement=strel('square', 8) ;
    threshold = imerode(threshold,erodeElement);
    threshold = imerode(threshold,erodeElement);
    threshold=imdilate(threshold, dilateElement);
    threshold=imdilate(threshold, dilateElement);
    threshold=imfill(threshold,'holes');
    subplot(2,2,4),imshow(threshold),title('形态学处理'),
 %}

%获取区域的'basic'属性, 'Area', 'Centroid', and 'BoundingBox' 
figure('name','处理结果'),
stats = regionprops(threshold, 'basic');
[C,area_index]=max([stats.Area]);
%定位马的区域
face_locate=[stats(area_index).Centroid(1),stats(area_index).Centroid(2)];
imshow(RGB);title('after'),hold on
text(face_locate(1),face_locate(2)-40,  '脸部','color','red');
plot(face_locate(1),face_locate(2), 'b*');
rectangle('Position',[stats(area_index).BoundingBox],'LineWidth',2,'LineStyle','--','EdgeColor','r'),
hold off 

在这里插入图片描述
在这里插入图片描述
7.代码汇总
如果你感觉粘贴代码不方便,建议:右键>“查看元素”>找到这一段的标签。
再右键>“查看源代码”>ctrl+F>找到标签,即可准确方便的复制到源代码的内容。

%初始化
clc;clear all;
close all;
%开始计时
tic
%输入需要识别的图像
[filename,pathname,fi]=uigetfile(...
                    {'*.*', 'all image file (*.*)';...
                     '*.bmp','all image file (*.bmp)';...
                     '*.jpg','all image file (*.jpg)'},...
                     '请选择要识别的图片',...
                     'MultiSelect', 'on');
in_image=imread([pathname filename]);
figure(1);imshow(in_image);title('原始图像1');%显示原始图像
imshow(in_image(:,:,3));
BW = im2bw(in_image(:,:,3),0.46); %将图片转为二值图片
figure(2);imshow(BW);title('去除背景1');
%实现对马的全阈值分割操作,将马从背景图片中完全分离
se1=strel('disk',7);%这里是创建一个半径为7的平坦型圆盘结构元素,合理调节strel()参数和使用腐蚀和膨胀的次数就可以很好地进行孔洞的填充。
BW=imerode(BW,se1);
figure;imshow(BW); 
se1=strel('disk',1);
BW=imerode(BW,se1);
figure;imshow(BW); 
se = strel('disk',9)
BW = imdilate(BW,se);%imerode
figure;imshow(BW); 
in_image(repmat(BW,[1,1,3])) = 0;
figure(3);imshow(in_image);title('去除背景2');
t=toc


%function:
%       基于颜色的图像分割;
%       定位图片中的马的区域;
%procession:
%       1.直接读入图片后,做二值化处理,根据数据游标的取值做初步的分割考察;
%       2.如果直接阈值分割不行,那需要考虑变换颜色空间来看是否便于图像分割;
%       3.在变换了颜色空间的图像上,通过数据游标直接选定大致的阈值,后续再手动改进;
%       4.分割后的图像常常会有孔洞,此时需要多次使用形态学方法(进行形态学处理:腐蚀、
%          膨胀、孔洞填充)来做孔洞填充;
%       5.图像拼接的话需要imresize()成相同大小的图片;
%       6.知识迁移到人脸识别应用中来,可以框出人脸位置区域


clear  all;
clc;
close all;
%开始计时
tic
%输入需要识别的图像
[filename,pathname,fi]=uigetfile(...
                    {'*.*', 'all image file (*.*)';...
                     '*.bmp','all image file (*.bmp)';...
                     '*.jpg','all image file (*.jpg)'},...
                     '请选择要识别的图片',...
                     'MultiSelect', 'on');
RGB=imread([pathname filename]); %界面手动选择读入方式
%RGB = imread('D:\Program Files\MATLAB\workspace\timg1.jpg'); %直接路径传入读取方式

figure('name','process'),
subplot(2,2,1),imshow(RGB),title('原始RGB'),

%convert frame from RGB to YCBCR colorspace(转换到YCBCR空间)
YCBCR = rgb2ycbcr(RGB);
whos,
subplot(2,2,2),imshow(YCBCR),title('YCBCR'),
%filter YCBCR image between values and store filtered image to threshold
%matrix(用各个通道的阈值对其进行二值化处理)
%% 通过数据游标直接选定大致的阈值,后续再手动改进
%Y_MIN = 40;  Y_MAX = 160;
%Cb_MIN = 80;   Cb_MAX = 120;
%Cr_MIN = 138;   Cr_MAX = 195;
%% 对马做阈值分割
 %{
Y_MIN = 40;  Y_MAX = 205; %到255也可以
Cb_MIN = 115;   Cb_MAX = 140;
Cr_MIN = 115;   Cr_MAX = 145; %已经是最佳,否则会引入背景噪声.
%}
Y_MIN =20;  Y_MAX = 160; %到255也可以
Cb_MIN = 100;   Cb_MAX = 150;
Cr_MIN = 110;   Cr_MAX = 170; %已经是最佳,否则会引入背景噪声.
threshold1=roicolor(YCBCR(:,:,1),Y_MIN,Y_MAX)&roicolor(YCBCR(:,:,2),Cb_MIN,Cb_MAX)&roicolor(YCBCR(:,:,3),Cr_MIN,Cr_MAX);
subplot(2,2,3),imshow(threshold1),title('YCBCR二值化'),

%perform morphological operations on thresholded image to eliminate noise
%and emphasize the filtered object(s)(进行形态学处理:腐蚀、膨胀、孔洞填充)
dilateElement=strel('square',13) ;
threshold=imdilate(threshold1, dilateElement);
erodeElement = strel('square', 4) ;
threshold = imerode(threshold,erodeElement);
erodeElement = strel('square', 3) ;
threshold = imerode(threshold,erodeElement);
erodeElement = strel('square', 2) ;
threshold = imerode(threshold,erodeElement);
threshold=imfill(threshold,'holes');
subplot(2,2,4),imshow(threshold),title('形态学处理');
% matlab多行注释
%{
    erodeElement = strel('square', 3) ;
    dilateElement=strel('square', 8) ;
    threshold = imerode(threshold,erodeElement);
    threshold = imerode(threshold,erodeElement);
    threshold=imdilate(threshold, dilateElement);
    threshold=imdilate(threshold, dilateElement);
    threshold=imfill(threshold,'holes');
    subplot(2,2,4),imshow(threshold),title('形态学处理'),
 %}

%获取区域的'basic'属性, 'Area', 'Centroid', and 'BoundingBox' 
figure('name','处理结果'),
stats = regionprops(threshold, 'basic');
[C,area_index]=max([stats.Area]);
%定位马的区域
face_locate=[stats(area_index).Centroid(1),stats(area_index).Centroid(2)];
imshow(RGB);title('after'),hold on
%text(face_locate(1),face_locate(2)-40,  '马','color','red');
text(face_locate(1),face_locate(2)-40,  '脸部','color','red');
plot(face_locate(1),face_locate(2), 'b*');
rectangle('Position',[stats(area_index).BoundingBox],'LineWidth',2,'LineStyle','--','EdgeColor','r'),
hold off 


%将五张图片拼接成一张完整的图像
RGB= imresize(RGB ,[1800 2307],'nearest')  % 'nearest'最近邻插值(默认),'bilinear'双线性插值,'bicubic'双三次插值
YCBCR= imresize(YCBCR ,[1800 2307],'nearest')  % 'nearest'最近邻插值(默认),'bilinear'双线性插值,'bicubic'双三次插值
threshold1= imresize(threshold1 ,[1800 2307],'nearest') 
threshold= imresize(threshold ,[1800 2307],'nearest') 
figure
imshow([RGB,YCBCR]) %面向对象的思想,将对象也当做最特殊的元素
figure
imshow([threshold1,threshold]) 
t=toc

参考:
https://www.cnblogs.com/chenyn2014/p/4220201.html
该博客提供了大量的matlab图像处理的例子和参考代码

https://www.cnblogs.com/zengke556/p/8053108.html
参考这里,实现了对马的像素的分割和剥离

猜你喜欢

转载自blog.csdn.net/jp_zhou256/article/details/86578797