???
《數(shù)字圖像處理》
期末大作業(yè)
班 ???級:數(shù)字媒體技術(shù)2020級1班
姓 ???名:快樂的小藍
學 ???號:XXXXXXXXX
XXXX大學信息學院
目錄
一、任務(wù)描述
二、設(shè)計思路
三、功能模塊
1 人臉定位
1.1 算法原理
1.檢測最大連通域
2.基于膚色的檢測
3.使用matlab自帶的工具人臉識別
1.2 算法實現(xiàn)(代碼)
1.3 實驗結(jié)果及對比分析
2 磨皮
2.1 算法原理
2.2 算法實現(xiàn)(代碼塊)
2.3 實驗結(jié)果及分析
3 放大眼睛
3.1 算法原理
3.2 算法實現(xiàn)
3.3 效果分析
4?縮小鼻頭
4.1 算法原理
4.2 算法實現(xiàn)(代碼)
4.3 效果分析
5?瘦臉
5.1 算法原理
5.2 算法實現(xiàn)(代碼)
5.3 效果分析
6?祛痘
6.1 算法原理
6.2 算法實現(xiàn)(代碼)
6.3 實驗結(jié)果及分析
7?素描效果
7.1 算法原理
7.2 算法實現(xiàn)
7.3 結(jié)果分析
8?油畫效果
8.1 算法原理
8.2算法實現(xiàn)
8.3效果分析
9?毛玻璃效果
9.1 算法原理
9.2 算法實現(xiàn)
9.3 效果分析
10?浮雕效果
10.1 算法原理
10.2 算法實現(xiàn)
10.3 效果分析
11?圖像旋轉(zhuǎn)
11.1 算法原理
11.2 算法實現(xiàn)
11.3 效果分析
12?圖像裁剪
12.1 算法原理
12.2 算法實現(xiàn)
12.3 效果分析
13?運動模糊
13.1 算法原理
13.2 算法實現(xiàn)
13.3 效果分析
14?圖像翻轉(zhuǎn)
14.1 算法原理
14.2 算法實現(xiàn)
14.3 效果分析
15?去除背景
15.1 算法原理
15.2 算法實現(xiàn)
15.3 效果分析
16?添加背景
16.1 算法原理
16.2 算法實現(xiàn)
16.3 效果分析
四、 創(chuàng)新點
人臉定位的實現(xiàn),最大連通域、膚色檢測、V-J算法
五、 心得體會
一、任務(wù)描述
選擇了簡易美圖秀秀,使用matlab的appdesigner實現(xiàn)了功能交互界面,功能模塊具體有定位人臉、磨皮、祛痘、大眼,縮小鼻翼等人臉處理功能。
二、設(shè)計思路
主要是參照美圖秀秀和平時學習相關(guān)的算法,實現(xiàn)了一個基礎(chǔ)版的美圖秀秀,但是平時所學還不足以支撐起這樣一個項目,所以我就根據(jù)自己要實現(xiàn)的功能,查閱了大量的資料和相關(guān)代碼實現(xiàn),進行了效果測試,以及代碼的修改。
三、功能模塊
1 人臉定位
1.1 算法原理
我在網(wǎng)上查了很多帖子,不涉及深度學習的算法主要有3種
1.檢測最大連通域
原理:通過對圖像進行形態(tài)學的處理,形成多個連通區(qū)域,默認最大的連通區(qū)域為人臉所在的區(qū)域。
缺陷:
1)有時候靜態(tài)的圖片,經(jīng)過形態(tài)學處理之后,最大的連通域并不是人臉的部分,所以這個算法局限性比較大。
2)只能對圖像中的一個人臉進行檢測
2.基于膚色的檢測
原理:膚色檢測的方法有很多,但是無論是基于不同的色彩空間還是不同的膚色模型,其根本出發(fā)點在于膚色分布的聚集性,即膚色的分量一般聚集在某個范圍內(nèi)。不同的色彩空間膚色的分布范圍不同。
1)RGB彩色空間
據(jù)統(tǒng)計資料,再均勻光照下,膚色分布范圍在:R>95且G>40且B>20且max{R,G,B}-min{R,G,B}>15,且|R-G|>15且R>G且R>B
2)YCbCr彩色空間
據(jù)資料統(tǒng)計,膚色在YCbCr彩色空間的分布范圍為77<=Cb<=127,133<=Cr<=173,下面就是使用的這個彩色空間進行基于膚色的人臉檢測,并且膚色模型用的是閾值模型,而沒有選擇高斯模型
3)HSV彩色空間
HSV空間建立的膚色檢測模型要求滿足0度<H<=25度或335度<=H<=360度且0.2<=S=0.6且0.4<=V
缺陷:
- 如果圖片背景或人的衣物與膚色相似,則定位不準確
- 有些加持了濾鏡的人像圖片,甚至檢測不到膚色像素。
3.使用matlab自帶的工具人臉識別
級聯(lián)對象檢測器使用Viola-Jones算法來檢測人的面部,鼻子,眼睛,嘴巴或上半身。還可以使用Image Labeler訓練自定義分類器以與此System對象一起使用。這個工具進行人臉定位比較準確,而且能實現(xiàn)嘴巴、鼻子、眼睛的輕松定位,在一張圖片中可以定位出多個人臉。
這個工具用算法都比較復(fù)雜,根據(jù)在網(wǎng)上查閱的博文,我有了大致的認識,總結(jié)如下:
這個檢測器用的算法是V-J算法,這個算法是以提出這個算法的兩位大佬命名的,Viola和Jones。實質(zhì)是,在AdaBoost算法的基礎(chǔ)上,使用Haar-like小波特征(簡稱haar特征)和積分圖的方法進行的人臉檢測。首先來看AdaBoost算法,這個算法本質(zhì)上是將多個弱分類器,組合成強的分類器。
- 初始化樣本,假設(shè)樣本數(shù)有N個,那么一開始每個樣本的權(quán)重為1/N。
- 訓練分類器,如果在分類的過程中,樣本被分類為正樣本,即這個樣本分類是準確的,那么在下一次分類迭代中,就會降低這個正樣本的權(quán)重,反之,如果是負樣本,則提高權(quán)重,迭代N次,得到使樣本分類的誤差函數(shù)值最小的分類器,這樣就得到了弱分類器,將多個弱分類器組合就得到強分類器。
那么AdaBoost的訓練樣本從何而來呢,那么就要說到Haar-like小波特征,雖然每個人都長的不一樣,但是人臉都有一些固定的特征,比如眼睛部分比較暗,鼻子兩側(cè)的比較暗,但中間部分比臉頰亮,嘴巴部分也比較暗,根據(jù)這些特征,V-J用了四種矩形特征,用黑色部分的灰度值減去白色部分的灰度值,就產(chǎn)生了人臉的矩形特征。一幅24*24的圖像就有160000個特征矩形,如果對這些特征矩形中所有像素點一次遍歷求和,計算量非常大,這時候積分圖就出現(xiàn)了。
積分圖,表征為位于(i,j)位置的像素點的積分是左上方所有像素的和,如果知道某些像素點的積分,求某個區(qū)域的像素和,只需要進行簡單的幾次加減,不需要每次遍歷。所以一張圖,將每個像素點都表征為積分,將積分值存儲在一個和原圖像大小相同的矩陣中,求指定區(qū)域的像素和的時候,只需要找出對應(yīng)位置的積分進行加減,就能得到這個區(qū)域的像素和,計算量大大減少了。
缺陷:有時候也會定位出不是嘴巴的部分,或者會將眼睛定位成嘴巴。
總的來說,按照效果排列:V-J算法>最大連通域>膚色檢測。
1.2 算法實現(xiàn)(代碼)
第一個是檢測最大連通域的人臉檢測代碼:
檢測最大連通區(qū)域
rgb = Img;
I = rgb2gray(rgb);%灰度化
[n1,n2] = size(I);%獲取圖像矩陣大小
%灰度圖
% figure,imshow(I),title('灰度圖')
tic
avel=fspecial('average',3);
I=filter2(avel,I)/255;
% figure,imshow(I),title('均值濾波')
BW = imbinarize(I);
% figure,imshow(BW),title('二值化')
B = ones(21);%結(jié)構(gòu)元素
?BW = -imerode(BW,B) + BW;
% BW=imdilate(BW,B)-imerode(BW,B);
% figure,imshow(BW),title('形態(tài)學邊界提取')
?BW = bwmorph(BW,'thicken');
% ?figure,imshow(BW),title('加粗邊界')
BW = ~(bwareaopen(~(BW), 50));%使用bwareaopen 函數(shù)刪除包含的像素數(shù)少于50的對象
% figure,imshow(BW),title('把空洞填了')
%進行形態(tài)學運算
B = strel('line',50,90);
BW = imdilate(BW,B);
BW = imerode(BW,B);
%figure,imshow(BW),title('閉運算操作之后')
B = strel('line',10,0);
BW = imerode(BW,B);
?figure,imshow(BW),title('閉操作之后再腐蝕')
BW = gpuArray(BW);%%將數(shù)據(jù)載入gpu可以加速,電腦不一定支持
%最小化背景
%細分
div = 10;
r = floor(n1/div);%分成10塊 行
c = floor(n2/div);%分成10塊 列
x1 = 1;x2 = r;%對應(yīng)行初始化
s = r*c;%塊面積
%判斷人臉是否處于圖片四周,如果不是就全部弄黑
for i=1:div
????y1 = 1;y2 = c;%對應(yīng)列初始化
????for j=1:div
????????loc = find(BW(x1:x2,y1:y2)==0);%統(tǒng)計這一塊黑色像素的位置
????????num = length(loc);
????????rate = num*100/s;%統(tǒng)計黑色像素占比
????????if (y2<=0.2*div*c||y2>=0.8*div*c)||(x1<=r||x2>=r*div)
????????????if rate <=100
????????????????BW(x1:x2,y1:y2) = 0;
????????????end
????????????imshow(BW)
????????else
????????????if rate <=25
????????????????BW(x1:x2,y1:y2) = 1;
????????????end
????????????%imshow(BW)
????????end%下一列
????????y1 = y1 + c;
????????y2 = y2 + c;
????end%下一行
????x1 = x1 + r;
????x2 = x2 + r;
end
figure
subplot(1,2,1)
imshow(BW)
title('最終處理')
L = bwlabel(BW,8);%利用belabel函數(shù)對8連通域區(qū)間進行標號
BB = regionprops(L,'BoundingBox');%得到矩形框,框出每一個連通域
BB = cell2mat(struct2cell(BB));
[s1,s2] = size(BB);
BB = reshape(BB,4,s1*s2/4)';
pickshape = BB(:,3)./BB(:,4);%
shapeind = BB(0.3<pickshape&pickshape<3,:);%篩選掉尺寸比例不合格
[~,arealind] = max(shapeind(:,3).*shapeind(:,4));
subplot(1,2,2)
imshow(rgb)
hold on
rectangle('Position',[shapeind(arealind,1),shapeind(arealind,2),shapeind(arealind,3),shapeind(arealind,3)],...
????'EdgeColor','g','Linewidth',2)
title('人臉檢測')
第二個是基于YCbCr顏色空間的人臉檢測
代碼塊:
%膚色檢測模型
image = imread('person10.jpg');
%三通道分離
image_red = image(:,:,1);
image_green = image(:,:,2);
image_blue = image(:,:,3);
[ROW,COL] = size(image_red);
figure
imshow(image);
title('原圖');
YCbCr = rgb2ycbcr(image);%將 RGB 圖像的紅色、綠色和藍色值轉(zhuǎn)換為 YCbCr 圖像的亮度 (Y) 和色度(Cb 和 Cr)值。
Y = YCbCr(:,:,1);
Cb = YCbCr(:,:,2);
Cr = YCbCr(:,:,3);
pic_gray = zeros(ROW,COL);%創(chuàng)建和原圖大小相同的全零矩陣
for i = 1:ROW
????for j = 1:COL
????????if(Cb(i,j) > 77 && Cb(i,j) < 127 && Cr(i,j) > 133 && Cr(i,j) < 173)
????????????pic_gray(i,j) = 255;
????????else
????????????pic_gray(i,j) = 0;
????????end
????end
end
figure
imshow(pic_gray);
title('膚色檢測圖');
se = strel('square',20);
erode = imerode(pic_gray,se);
figure
imshow(erode);
title('形態(tài)學濾波');
x_min = 1024;
x_max = 0;
y_min = 768;
y_max = 0;
for i = 1:ROW
????for j = 1:COL
????????if(erode(i,j) > 0 && x_min > j)
????????????x_min = j;
????????end
????????if(erode(i,j) > 0 && x_max < j)
????????????x_max = j;
????????end
????end
end
for i = 1:ROW
????for j = 1:COL
????????if(erode(i,j) > 0 && y_min > i)
????????????y_min = i;
????????end
????????if(erode(i,j) > 0 && y_max < i)
????????????y_max = i;
????????end
????end
end
for i = 1:ROW
????for j = 1:COL
????????if(j == x_min && i >= y_min && i <= y_max)
????????????image_test(i,j,1) = uint8(255);
????????????image_test(i,j,2) = uint8(255);
????????????image_test(i,j,3) = uint8(255);
????????elseif(j == x_max && i >= y_min && i <= y_max)
????????????image_test(i,j,1) = uint8(255);
????????????image_test(i,j,2) = uint8(255);
????????????image_test(i,j,3) = uint8(255);
????????elseif(i == y_max && j >= x_min && j <= x_max)
????????????image_test(i,j,1) = uint8(255);
????????????image_test(i,j,2) = uint8(255);
????????????image_test(i,j,3) = uint8(255);
?????????elseif(i == y_min && j >= x_min && j <= x_max)
????????????image_test(i,j,1) = uint8(255);
????????????image_test(i,j,2) = uint8(255);
????????????image_test(i,j,3) = uint8(255);
????????else
????????????image_test(i,j,1) = image(i,j,1);
????????????image_test(i,j,2) = image(i,j,2);
????????????image_test(i,j,3) = image(i,j,3);
????????end
????end
end
%subplot(2,2,4);
figure
imshow(image_test);
title('頭像檢測');
第三個是利用matlab工具來進行人臉的定位
代碼塊:
detector = vision.CascadeObjectDetector;%獲取檢測器
%Read the input image
I = imread('person.jpg');%讀入圖像
face_dtect = step(detector,I);%人臉檢測,返回人臉區(qū)域的位置向量
figure
imshow(I)%顯示圖像
?hold on
for i = 1:size(face_dtect,1)%檢測器可能檢測到多個
????rectangle('Position',face_dtect(i,:),'LineWidth',1,'LineStyle','-','EdgeColor','m');%用矩形標注出人臉區(qū)域
end
title('人臉檢測');
1.3 實驗結(jié)果及對比分析
膚色檢測:
結(jié)果分析:
對于背景和人物衣物顏色與膚色閾值不相近的圖像來說,效果比較好,但是大部分測試圖像定位都不準確,尤其是人臉區(qū)域很小,或者人物的衣物與背景和膚色閾值接近,效果就很差。
最大連通域:
??
結(jié)果分析:最大連通域默認整個圖像的最大連通域就是人臉,所以對于人臉占圖像比例大的圖片,處理效果就很好(也不是越大越好,人臉盡量要完整),但是像第二張圖片,整個小姑娘站的較遠,且是側(cè)身站的,人臉部分出現(xiàn)了較大的斷裂,無法連通,所以檢測出來的結(jié)果完全錯誤。但總體來說測試效果成功的概率比膚色檢測好很多。
V-J算法:
結(jié)果分析:
這個算法人臉定位比較準確,甚至還可以定位五官和上半身。對正臉的圖像準確率高一些,人臉部分可以比較小,但必須完整。上面的倒數(shù)兩張圖定位失敗了,倒數(shù)第二張定位出了兩張人臉,人物的衣服結(jié)構(gòu)復(fù)雜,檢測器把它也作為人臉了,最后一張直接沒有檢測出人臉,誤差比較大,而且,我在測試檢測五官的時候,我發(fā)現(xiàn)這個檢測器在檢測嘴巴的時候,往往將眼睛也標記出來了,但是檢測鼻子比較精準。但是整體效果比前面兩種算法好很多。
2 磨皮
2.1 算法原理
磨皮:實質(zhì)上就是圖像的平滑,根據(jù)目前的學到的平滑圖像的算法,空域有高斯濾波、中值濾波、均值濾波,頻域就是低通濾波器。我在測試的時候,發(fā)現(xiàn)這個濾波器會模糊五官和邊界,效果很不理想。翻看教材,發(fā)現(xiàn)教材上使用了雙邊濾波進行人臉的磨皮。看書上的公式腦袋暈乎乎的,但是聽了專業(yè)同學的講解,發(fā)現(xiàn)這個算法也不難。
這算法是在高斯濾波上的改進,高斯濾波只考慮了位置對像素值的影響,即位置越近,對像素值的影響越大,所以這樣會模糊掉邊界等重要信息。而雙邊濾波,將位置和像素值看得同等重要,在平坦區(qū)域,像素的位置主導(dǎo)雙邊濾波的效果。在邊緣區(qū)域,由于邊緣兩側(cè)像素值相差很大,所以邊緣另一側(cè)的像素權(quán)重降低,幾乎不會影響到邊緣這一側(cè)的像素,這就實現(xiàn)了保邊的效果。
2.2 算法實現(xiàn)(代碼塊)
%用雙邊濾波實現(xiàn)人臉美化的效果
I = imread('person2.jpg');%讀取圖像
figure(1)
imshow(I),title('原圖');%顯示原圖
bfilt_rgb(I,15,6,0.1);%調(diào)用雙邊濾波函數(shù),進行濾波處理
%函數(shù)實現(xiàn)
function g = bfilt_rgb(f,r,a,b)
% f彩色圖;r濾波半徑;a全局方差;b局部方差
[x,y] = meshgrid(-r:r);%創(chuàng)建二維網(wǎng)格坐標
w1 = exp(-(x.^2+y.^2)/(2*a^2));%計算濾波內(nèi)的空間權(quán)值
f = im2double(f);%將uint8轉(zhuǎn)換成double,方便后續(xù)處理
h = waitbar(0,'Applying bilateral filter...');%設(shè)置進度條
set(h,'Name','Bilateral Filter Progress');
detector = vision.CascadeObjectDetector;%目標探測器
facePart = step(detector,f);
%獲取臉部坐標
X_min = facePart(1,1);%人臉區(qū)域的左下x坐標
Y_min = facePart(1,2);%y坐標
Width = facePart(1,3);%區(qū)域?qū)挾?
Height = facePart(1,4);%區(qū)域高度
%三通道分離
fr = f(:,:,1);
fg = f(:,:,2);
fb = f(:,:,3);
[m,n] = size(fr);%圖像矩陣大小,方便后面像素的遍歷
fr_temp = padarray(fr,[r r],'symmetric');%鏡像填充矩陣,方便處理邊界像素
fg_temp = padarray(fg,[r r],'symmetric');%鏡像填充矩陣,方便處理邊界像素
fb_temp = padarray(fb,[r r],'symmetric');%鏡像填充矩陣,方便處理邊界像素
[gr,gg,gb] = deal(zeros(size(fr)));%創(chuàng)建三個和原圖像大小相同的全零矩陣
for i = r+1+Y_min:Height+Y_min+r%對人臉部分進行雙邊濾波
????for j = r+1+X_min:X_min+Width+r
????????temp1 = fr_temp(i-r:i+r,j-r:j+r);%三通道的濾波區(qū)域31X31的正方形
????????temp2 = fg_temp(i-r:i+r,j-r:j+r);
????????temp3 = fb_temp(i-r:i+r,j-r:j+r);
????????dr = temp1 - fr_temp(i,j);
????????dg = temp2 - fg_temp(i,j);
????????db = temp3 - fb_temp(i,j);
????????w2 = exp(-(dr.^2+dg.^2+db.^2)/(2*b^2));%求濾波內(nèi)每個像素對目標像素的影響權(quán)值(基于像素值)
????????w = w1.*w2;%將兩種權(quán)值相加,求得濾波范圍內(nèi)每個像素的最終權(quán)值
????????gr(i-r,j-r) = sum(sum(temp1.*w))/sum(w(:));%將權(quán)值與對應(yīng)像素值相乘相加,再除以權(quán)值和,即求得該像素點經(jīng)雙邊濾波后的像素值
????????gg(i-r,j-r) = sum(sum(temp2.*w))/sum(w(:));
????????gb(i-r,j-r) = sum(sum(temp3.*w))/sum(w(:));
????end
????waitbar((i-r)/n);%進度條
end
%將人臉部分賦黑,方便后面圖像的疊加
for m=X_min+2:X_min+Width
????for n=Y_min+1:Height+Y_min
????????f(n,m,1)=0;
????????f(n,m,2)=0;
????????f(n,m,3)=0;
????end
end
g = cat(3,gr,gg,gb);%串聯(lián)數(shù)組,合并三通道
result=imadd(g,f);
figure(2)
imshow(result),title('雙邊濾波');%顯示處理圖
end
2.3 實驗結(jié)果及分析:
效果分析:雙邊濾波既平滑了皮膚,又保留了五官部分,效果真的很好,就是處理速度慢一些。
3 放大眼睛
-
- 算法原理
首先是利用matlab工具箱的人臉檢測器,檢測出兩只眼睛的位置向量,然后分別對兩只眼睛進行放大處理:先根據(jù)每只眼睛的位置向量確定放大區(qū)域的中心坐標,然后設(shè)置放大區(qū)域的邊長,遍歷需要放大的區(qū)域,使用最鄰近插值法,得到放大后的像素值,遍歷完成之后,放大效果就實現(xiàn)了。
3.2 算法實現(xiàn)?
%放大眼睛
I = imread('person13.jpg');%讀入圖像
I = im2double(I);%數(shù)據(jù)類型轉(zhuǎn)化,以便后續(xù)處理
%V-J算法檢測眼睛
detector = vision.CascadeObjectDetector;%調(diào)用檢測器
detector.ClassificationModel='LeftEyeCART';%調(diào)用眼睛檢測器
bboxes = detector(I);%檢測眼睛,返回眼睛區(qū)域的位置向量
%放大眼睛
strength=20;%放大強度
pointx=floor(bboxes(1,2)+(bboxes(1,3)/2));%根據(jù)檢測器大致確定眼睛中心點
pointy=floor(bboxes(1,1)+(bboxes(1,4)/2))+10;
r=50;%放大區(qū)域邊長
left=pointy-r;
right=pointy+r;
top=pointx-r;
bottom=pointx+r;
space=r*r;%放大的正方形區(qū)域
I1=I;%將原圖緩存,存儲處理后的圖像
for x=top:bottom%遍歷放大區(qū)域的像素
????offsetx=x-pointx;
????for y=left:right
????????offsety=y-pointy;
????????xy=offsetx*offsetx+offsety*offsety;
????????if xy<=space
????????????scale=1-xy/space;
????????????scale=1-strength/100*scale;
????????????%減少計算量,采用最鄰近插值,利用四舍五入函數(shù)實現(xiàn)
????????????posy=round(offsety*scale+pointy);%放大后的Y坐標值
????????????posx=round(offsetx*scale+pointx);%放大后的X坐標值
????????????%分別對三通道進行處理
????????????I1(x,y,1)=I(posx,posy,1);
????????????I1(x,y,2)=I(posx,posy,2);
????????????I1(x,y,3)=I(posx,posy,3);
????????end
????end
end
pointx=floor(bboxes(2,2)+(bboxes(2,3)/2));%對另一只眼睛進行同樣的處理
pointy=floor(bboxes(2,1)+(bboxes(2,4)/2));
r=50;
left=pointy-r;
right=pointy+r;
top=pointx-r;
bottom=pointx+r;
space=r*r;
I2=I1;
for x=top:bottom
????offsetx=x-pointx;
????for y=left:right
????????offsety=y-pointy;
????????xy=offsetx*offsetx+offsety*offsety;
????????if xy<=space
????????????scale=1-xy/space;
????????????scale=1-strength/100*scale;
????????????posy=round(offsety*scale+pointy);
????????????posx=round(offsetx*scale+pointx);
????????????I2(x,y,1)=I1(posx,posy,1);
????????????I2(x,y,2)=I1(posx,posy,2);
????????????I2(x,y,3)=I1(posx,posy,3);
????????end
????end
end
figure
subplot(121),imshow(I2),title('放大眼部');
subplot(122),imshow(I),title('原圖');
3.3 效果分析
效果分析:因為這個功能主要是基于人眼的位置識別,所以人眼位置定位是否準確,直接影響了眼部增大功能的實現(xiàn)效果,對于有些人像圖,甚至檢測不到眼部,所以就根本不能使用該功能,還有些人像,會將嘴巴部分也識別成眼部,所以會導(dǎo)致嘴巴部分被放大,但是只要是能準確定位眼部的,處理效果就很不錯。
4?縮小鼻頭
4.1 算法原理
這個算法依舊是基于人臉檢測V-J和區(qū)域放縮算法,并且步驟與眼睛放大大同小異。首先使用matlab定位到鼻子的位置,然后根據(jù)工具返回的位置向量確定鼻子的中心坐標,最后使用區(qū)域放大算法,只不過將強度改為負數(shù),就達到了區(qū)域縮小的效果,即鼻頭縮小術(shù)。
4.2 算法實現(xiàn)(代碼)
%瘦鼻
I = imread('person25.jpg');
detector = vision.CascadeObjectDetector;%檢測器
detector.ClassificationModel='Nose';
detector.MergeThreshold=10;%增加合并閾值
bboxes=detector(I);
Nose=insertObjectAnnotation(I,'rectangle',bboxes,'Nose');%用矩形框標出鼻子定位的矩形區(qū)域
figure(9);imshow(Nose);title('Nose'); %顯示圖像
%區(qū)域圖像縮小
strength=-20;%縮小強度
pointx=floor(bboxes(1,2)+(bboxes(1,3)/2));%根據(jù)檢測器大致確定鼻子中心點
pointy=floor(bboxes(1,1)+(bboxes(1,4)/2));
r=50;%放大區(qū)域邊長
left=pointy-r;
right=pointy+r;
top=pointx-r;
bottom=pointx+r;
space=r*r;%縮小的正方形區(qū)域
I1=I;%將原圖緩存,存儲處理后的圖像
for x=top:bottom%遍歷縮小區(qū)域的像素
????offsetx=x-pointx;
????for y=left:right
????????offsety=y-pointy;
????????xy=offsetx*offsetx+offsety*offsety;
????????if xy<=space
????????????scale=1-xy/space;
????????????scale=1-strength/100*scale;
????????????%減少計算量,采用最鄰近插值,利用四舍五入函數(shù)實現(xiàn)
????????????posy=round(offsety*scale+pointy);%放大后的Y坐標值
????????????posx=round(offsetx*scale+pointx);%放大后的X坐標值
????????????%分別對三通道進行處理
????????????I1(x,y,1)=I(posx,posy,1);
????????????I1(x,y,2)=I(posx,posy,2);
????????????I1(x,y,3)=I(posx,posy,3);
????????end
????end
end
figure
imshow(I1);
4.3 效果分析
效果分析:這個功能幾乎跟放大眼睛的功能相同,所以只要鼻子定位準確,鼻翼縮小的效果是很好的,但是對于定位不到鼻子的人像,就無法進行縮小處理了,而且我發(fā)現(xiàn)了一個神奇的現(xiàn)象,原來鼻頭變小,會有視覺上放大眼睛的效果。
5?瘦臉
5.1 算法原理
這個算法主要是基于像素平移,我參考的是網(wǎng)上有一篇液化算法的帖子,里面給出了逆變換公式和算法實現(xiàn)的步驟,沒有給出實現(xiàn)代碼,所以,我一開始對這個算法理解不深的時候,根本無法寫出實現(xiàn)的代碼,但是后面我再次去看這個算法的時候,發(fā)現(xiàn)這個算法實際上就是像素平移,因為平移的像素到達目的位置的時候,由于根據(jù)變換公式算出來的坐標是雙精度的,而圖像的矩陣的坐標是正整數(shù),所以平移的時候,無論用什么插值算法,都有可能出現(xiàn)像素的重疊或者缺失像素值的問題,所以采用逆變換,用目的位置來倒推原來的像素的位置,因為倒推出來也是雙精度,所以對原來像素值鄰近像素使用雙線性插值算法,算出的像素值就是目的位置上的像素值,這樣就實現(xiàn)了像素比較平滑的平移。算法實現(xiàn)之后,我用的是交互式選取圓形區(qū)域,然后再選取一個平移的圓心,目的是對臉部邊緣的像素平滑平移,從而從視覺效果上實現(xiàn)瘦臉的效果,但實際上操作起來,一旦選取的區(qū)域與目的圓心的位置相距太遠,就會產(chǎn)生畸變,導(dǎo)致臉部嚴重變形,我嘗試了很多人臉圖像,只有一張效果還不錯,但是也是要經(jīng)過很多次像素的不明顯平移,才會看出比較明顯的瘦臉效果。我一直在想怎么完善一下,但是時間好像不夠了,就放棄了。
5.2 算法實現(xiàn)(代碼)
for cou =1:300
????if cou==1
????????I = imread('C:\Users\leishen\Desktop\數(shù)字圖像處理\期末大作業(yè)\測試效果\person7.jpg');%讀入圖片
????else
????????I = imread('C:\Users\leishen\Desktop\數(shù)字圖像處理\期末大作業(yè)\測試效果\person25.jpg');%讀入修改之后的圖片,以便繼續(xù)進行瘦臉處理
????end
????figure
????imshow(I);
????h = drawcircle('Color','k','FaceAlpha',0.4);%交互式選取圓形區(qū)域
????M = ginput(1); ?%交互式選取坐標,即變化后的圓心的位置
????[m,n,~] = size(I);%圖像矩陣的大小
????center = [floor(h.Center(2)),floor(h.Center(1))];%變形前的圓心
????radius = h.Radius;%變形的圓半徑
????RGB_buff = I;
????%遍歷圓形選區(qū)的每一個像素
????for i=1:m
????????for j=1:n
????????????distant = sqrt((i-center(1)).^2+(j-center(2)).^2);%判斷該像素點是否在選取的圓形區(qū)域內(nèi)
????????????if distant <= radius
????????????????x = [i,j];%變形后的坐標
????????????????U = x - ((radius^2 - (x - center).^2) / (radius^2 - (x - center).^2 + (M - center).^2))^2 * (M - center);%逆變換公式
????????????????uu = floor(U);%舍棄小數(shù)部分,保留整數(shù)
????????????????ab = U-uu;%這個數(shù)據(jù)用于后面雙線性插值處理
????????????????a = ab(1);
????????????????b = ab(2);
????????????????m1 = uu(1);
????????????????n1 = uu(2);
????????????????for k=1:3
????????????????I(i,j,k)=(1-a)*(1-b)*RGB_buff(m1,n1,k)+a*(1-b)*RGB_buff(m1+1,n1,k)+(1-a)*b*RGB_buff(m1,n1,k)+a*b*RGB_buff(m1+1,n1+1,k);%雙線性插值
????????????????end ????
????????????end
????????end
????end
????figure
????imshow(I);
????
????answer = questdlg('是否要繼續(xù)調(diào)整', ...
????'選擇', ...
????'YES','NO','NO');
????
????switch answer
????????case 'YES'
????????????imwrite(I,'C:\Users\leishen\Desktop\數(shù)字圖像處理\期末大作業(yè)\測試效果\person25.jpg');
????????case 'NO'
????????????msgbox("退出調(diào)整");
????????break;
????end
end
5.3 效果分析
可以看到臉部的左邊實現(xiàn)了較大的像素平移效果,所以從視覺上有了瘦臉的效果,但是仔細看,就會發(fā)現(xiàn)像素平移造成了圖像的局部畸變和模糊。
6?祛痘
6.1 算法原理
這個實現(xiàn)原理比較簡單,先交互式選取想要祛痘的區(qū)域,然后提取這個區(qū)域的左上角的第一個像素,用這個像素值-5到像素值+5范圍的像素值,隨機的填充選取的區(qū)域。然后為了減弱填充的邊界,用了高斯濾波對臉部進行了高斯濾波的處理。
6.2 算法實現(xiàn)(代碼)
g=imread('person1.jpg');
% n 為操作次數(shù),默認為1,g為原圖
n=3;
g2 = g;
%得到原圖像的大小
[ M,N,~ ] = size( g );
while( n ~=0 )
????n = n - 1;
????%進行交互選擇處理區(qū)域
????mask = roipoly( g2 );%roipoly函數(shù)--指定多邊形感興趣區(qū)域,將蒙版作為二進制圖像返回,所以下面的乘法就可以得到原圖像被提取的區(qū)域,因為0的部分乘以任何像素值都為0,1乘以原像
????%素還是等于原像素
????x1 = immultiply( mask,g2( :,:,1 ) );
????x2 = immultiply( mask,g2( :,:,2 ) );
????x3 = immultiply( mask,g2( :,:,3 ) );
????x = cat( 3,x1,x2,x3 );%將x1和x2和x3沿第三維度串聯(lián)起來,這里相當于三通道合并
% ?figure
% ?imshow(x);%原來x是交互時提取的區(qū)域
????%預(yù)分配內(nèi)存,f1,f2,f3存儲三個通道的運算結(jié)果
????f1 = zeros( M,N );
????f2 = zeros( M,N );
????f3 = zeros( M,N );
????%跳出雙重循環(huán)設(shè)置flag
????flag = 0;
????%找到第一個像素值不為0的點,得到該點像素值,作為采樣后填充的像素
????for i = 1:M
????????for j = 1:N
????????????if( x1( i,j ) ~= 0 )
????????????????r = x( i,j,: );
????????????????flag = 1;%找到之后,跳出循環(huán)
????????????????break
????????????end
????????????if( flag == 1 )
????????????????break
????????????end
????????end
????end
????
????%隨機產(chǎn)生填充圖像,這就是填充痘印部分的圖像
????y = zeros(3,3,3);
????y( :,:,1 ) = randi([r(1)-5,r(1)+5],[3,3]);%取像素值-5到像素值+5的范圍的隨機數(shù)組成一個3X3的矩陣
????y( :,:,2 ) = randi([r(2)-5,r(2)+5],[3,3]);
????y( :,:,3 ) = randi([r(3)-5,r(3)+5],[3 3]);
????
????%類型轉(zhuǎn)換
????y = double(y);
????%對于三個通道分別進行處理,用采樣得到的像素點取代原來的像素點
????for i = 2:3:M-1
????????for j = 2:3:N-1
????????????f1( i-1:i+1,j-1:j+1 ) = mask( i-1:i+1,j-1:j+1 ).* y( :,:,1 );
????????????f2( i-1:i+1,j-1:j+1 ) = mask( i-1:i+1,j-1:j+1 ).* y( :,:,2 );
????????????f3( i-1:i+1,j-1:j+1 ) = mask( i-1:i+1,j-1:j+1 ).* y( :,:,3 );
????????end
????end
????%將三個通道連接在一起
????f = cat( 3,f1,f2,f3 );
????%類型轉(zhuǎn)換
????f = uint8( f );
????
????%得到處理后圖像,居然可以直接加減,那還學什么運算函數(shù)
????a = g2 - x;
????f = f + a;
????g2 = f;
end
%圖像濾波處理,將圖像進行高斯濾波處理,平滑
f = double(f);
b = double( imguidedfilter( uint8( f ) ) ) - f + 128 ;
t = imfilter( b, fspecial( 'gaussian',[5 5]) );
f = ( f*50 + ( f+2*t-256 )*50 )/100;
f = uint8(f);
%顯示圖像
subplot( 1,2,1 ),imshow( g ),title('原圖');
subplot( 1,2,2 ),imshow( f ),title('填充處理后圖像');
6.3 實驗結(jié)果及分析
結(jié)果分析:因為祛痘區(qū)域的像素是根據(jù)區(qū)域左上角第一個像素+5-5這個范圍,進行隨機填充的??梢钥吹?,如果痘痘長到臉部死角的話,填充效果是很突兀的,就算是平坦區(qū)域,人臉和填充區(qū)域也沒有很好的連接,填充區(qū)域比較突兀,盡管進行了高斯濾波,效果還是一般,但是對于沒有高光的人臉,祛痘效果應(yīng)該不錯。
7?素描效果
7.1 算法原理
實質(zhì)上就是紋理的一個提取過程,首先是分離三通道,隨便選擇一個通道進行處理,然后將這通道取反,再用高斯濾波對負片進行濾波處理,去除一些噪點,最后就是按照比例將正片和負片進行疊加,最后歸一化之后,就得到了比較理想的素描效果。
7.2 算法實現(xiàn)(代碼塊)
I = imread('person11.jpg');
[height,width,~]=size(I);%獲取圖像矩陣的大小
N=zeros(height,width);%創(chuàng)建兩個全零矩陣
G=zeros(height,width); ?
%分離三通道
rc = I(:,:,1);
gc = I(:,:,2);
bc = I(:,:,3);
%選擇一個通道進行處理
channel = gc;
out=zeros(height,width); ?
spec=zeros(height,width,3); ?
%顏色取反
for i=1:height
????for j=1:width
????????N(i,j)=uint8(255-channel(i,j));
????end ?
end ??
%高斯模糊
gausize = 10;%濾波器大小,越大越模糊
gausigma = 12; %越大越模糊
GH = fspecial('gaussian', gausize, gausigma);%構(gòu)建高斯濾波模板
G = imfilter(N, GH);%濾波處理
for i=1:height ?
????for j=1:width ?
????????b=double(G(i,j)); ?
????????a=double(channel(i,j)); ?
????????temp=a+a*b/(256-b);%將濾波后的負片和正片相疊加
????????out(i,j)=uint8(min(temp,255)); ?
????end ?
end ?
%模糊程度越高,得到的素描結(jié)果越清晰,框架紋理顏色越深
figure
subplot(121),imshow(out/255);%歸一化處理并顯示圖像
subplot(122),imshow(I);
7.3 結(jié)果分析
效果分析:圖片越清晰,效果越好,因為這個處理主要是對紋理進行提取,進而實現(xiàn)了類似素描的效果。
8?油畫效果
8.1 算法原理
定義一個矩形窗口,用這個窗口劃過圖像的每一個像素點(三通道分別處理),計算矩形內(nèi)每一個像素點的灰度值,取這個區(qū)域里面最大的像素值作為當前像素點的值,這樣就實現(xiàn)了簡單的油畫效果。
8.2算法實現(xiàn)(代碼塊)
A=imread('person4.jpg'); ?????????
?????????% 油畫效果
%創(chuàng)建12X12的窗口矩陣,窗口越大,丟失的信息就越多,效果就越明顯
m=12;
n=12;
Image=uint8(zeros([size(A,1)-m,size(A,2)-n,3]));
figure
imshow(Image);
%計算每個RGB值的直方圖
for v=1:3
for i=1:size(A,1)-m
????for j=1:size(A,2)-n
????????mymask=A(i:i+m-1,j:j+n-1,v);
????????h=zeros(1,256);
????????for x=1:(m*n)
????????????h(mymask(x)+1)=h(mymask(x)+1)+1;
????????end
????????[maxvalue,pos]=max(h);%記錄最大值和最大值對應(yīng)的位置
????????Image(i,j,v)=pos-1;%將最大值賦值給當前的像素
????end
end
end
figure
subplot(121),imshow(Image);
subplot(122),imshow(A);
8.3效果分析
效果分析:窗口越大,效果越明顯,但是由于取的是最大值,所以有些地方突變很突兀,效果不是很理想,但基本實現(xiàn)了油畫效果。
9?毛玻璃效果
9.1 算法原理
首先創(chuàng)建一個處理的窗口,可以自定義大小,然后用這個窗口滑動圖像的每一個像素,隨機取這個窗口的某個像素,賦值給當前滑過的像素,直至遍歷所有像素,毛玻璃效果就完成了。
9.2 算法實現(xiàn)(代碼塊)
A=imread('buiding1.jpg');%讀入圖像
%定義一個6X7的矩形窗口
m=6; ?????????????????????????????????????????????????????????????????
n=7;
Image=uint8(zeros([size(A,1)-m,size(A,2)-n,3]));%存儲窗口處理后的圖像
for i=1:size(A,1)-m
????for j=1:size(A,2)-n
????????mymask=A(i:i+m-1,j:j+n-1,:);%將圖像對應(yīng)像素值賦值給窗口
x2=ceil(rand(1)*m);%從窗口像素隨機挑選一個像素,因為坐標必須為正整數(shù),所以用ceil四舍五入為整數(shù)
y2=ceil(rand(1)*n);
????????Image(i,j,:)=mymask(x2,y2,:);%將選出的像素值賦值給當前的像素
????end
end
imshow(Image);%顯示圖像
9.3 效果分析
10?浮雕效果
10.1 算法原理
這個效果的實現(xiàn)比較簡單,實質(zhì)上就是提取圖像的邊界,然后突出邊界。具體步驟就是對灰度圖進行Sobel濾波,提取邊界,然后再進行灰度轉(zhuǎn)化。
10.2 算法實現(xiàn)(代碼塊)
img=imread('building2.jpg');%讀入圖像
f0=rgb2gray(img);%改為灰度圖像
f1=im2double(f1);
h2=fspecial('sobel'); %進行sobel濾波
g3=filter2(h2,f1,'same');
K=mat2gray(g3); %將矩陣轉(zhuǎn)換成灰度圖
figure
imshow(K);
10.3 效果分析
效果分析:浮雕效果取決于邊界提取的效果,所以灰度值變化大的圖像,處理效果就很好,所以這個效果對建筑物等圖片處理效果還可以,就貼了一張?zhí)幚斫ㄖ锏膱D片。
11?圖像旋轉(zhuǎn)
11.1 算法原理
實質(zhì)上就是矩陣的旋轉(zhuǎn),旋轉(zhuǎn)軸是圖像的中心,讓圖像的每一個坐標經(jīng)過旋轉(zhuǎn)公式計算出旋轉(zhuǎn)后的坐標,但是計算出來的坐標是浮點數(shù),坐標必須是正整數(shù),所以必須取整,但是取整后,可能有些坐標上像素值會出現(xiàn)重疊,有些坐標上可能出現(xiàn)沒有像素的情況,所以用變換后的坐標來確定變換前的坐標,然后用變換前坐標附近的像素點進行簡單的線性插值,算出變換后坐標的像素值,遍歷完圖像之后,就得到了旋轉(zhuǎn)后的圖像。
11.2 算法實現(xiàn)(代碼塊)
%圖像旋轉(zhuǎn)
I = imread('person10.jpg');%讀入圖像
I = im2double(I);
I2=imrotate(I,-22);
figure
subplot(121),imshow(I2),title('順時針旋轉(zhuǎn)22度');%調(diào)用函數(shù)實現(xiàn)
%自己寫代碼實現(xiàn)
%旋轉(zhuǎn)22度
a = 22/180*pi;%角度轉(zhuǎn)換成弧度
Rotate = [cos(a) -sin(a);sin(a) cos(a)];%旋轉(zhuǎn)變換矩陣
[m,n,~] = size(I);%矩陣大小
center = [m,n]/2;%旋轉(zhuǎn)軸中心
% 計算顯示完整圖像需要的畫布大小
hh = floor(m*sin(a)+n*cos(a))+1;
ww = floor(m*cos(a)+n*sin(a))+1;
c2 = [hh; ww] / 2;%旋轉(zhuǎn)之后的軸中心
res = zeros(size(I));%創(chuàng)建存儲結(jié)果的全零矩陣
for k=1:3%三個通道
?for i=1:hh
?????for j=1:ww
?????????R = Rotate*([i;j]-c2)+center;%變換公式
?????????R1 = floor(R);%向負無窮舍入
?????????ab = R-R1;%線性插值算法
?????????a = ab(1);
?????????b = ab(2);
?????????m1 = R1(1);
?????????n1 = R1(2);
?????????if (R(1) >= 1 && R(1) <= m && R(2) >= 1 && R(2) <= n)
?????????????res(i, j, k) =(1-a)*(1-b)*I(m1,n1, k) + a*(1-b)*I(m1+1, n1, k)...
??????????????????????????+ (1-a)*b*I(m1,n1+1,k)+ a*b*I(m1+1,n1+1, k);%簡單線性插值
?????????end
?????end
?end
end
?subplot(122),imshow(res),title('順時針旋轉(zhuǎn)變化22');%顯示圖像
11.3 效果分析
對于自編程的函數(shù)實現(xiàn)旋轉(zhuǎn),存在圖片的拉伸,和圖片顯示不完整等問題,算法實現(xiàn)還是有一定問題。
12?圖像裁剪
12.1 算法原理
利用交互式函數(shù)提取裁剪的區(qū)域,然后根據(jù)返回的參數(shù),顯示裁剪后的圖像。
12.2 算法實現(xiàn)(代碼塊)
%交互式裁剪圖像
I =imread(‘person.jpg’);%讀取圖像
[J,rect] = imcrop(I);調(diào)用函數(shù)交互式裁剪圖像,J返回的是裁剪的區(qū)域,rect返回的是指定裁剪區(qū)域的四元素位置向量。
I2 = imcrop(I,rect);%根據(jù)返回的位置向量裁剪圖像并返回
imshow(I2);%顯示裁剪的圖像
12.3 效果分析
效果分析:這個就是實現(xiàn)了交互式裁剪。
13?運動模糊
13.1 算法原理
利用matlab函數(shù)fspecial,通過設(shè)置運動位移參數(shù)和位移角度參數(shù),得到運動仿真濾波器,然后利用濾波器進行圖像濾波,得到運動模糊后的圖像。
13.2 算法實現(xiàn)(代碼塊)
%運動模糊
????????????I = imread('buiding1.jpg');%讀入圖像
????????????len=20;%設(shè)置運動位移為20個像素
????????????theta=50;%設(shè)置運動角度為45度
????????????psf = fspecial('motion',len,theta);%建立二維運動仿真濾波器psf
????????????j = imfilter(I,psf,'circular','conv');%用濾波器產(chǎn)生退化圖像
????????????figure
????????????subplot(121),imshow(j),title('運動模糊');%顯示運動模糊圖像
????????????subplot(122),imshow(I),title('原圖');%顯示原圖像
13.3 效果分析
14?圖像翻轉(zhuǎn)
14.1 算法原理
圖像的翻轉(zhuǎn)實質(zhì)上就是矩陣上元素序列的反轉(zhuǎn),flip這個函數(shù),如果里面只有需要翻轉(zhuǎn)的圖像I的話,默認翻轉(zhuǎn)每一列每一行的元素序列,如果在后面加上維度1,就是翻轉(zhuǎn)每一列的元素序列,就實現(xiàn)了上下翻轉(zhuǎn)的效果,如果在后面加上維度2,就是翻轉(zhuǎn)每一行的元素序列,就實現(xiàn)了左右翻轉(zhuǎn)的效果。
14.2 算法實現(xiàn)(代碼塊)
%圖像翻轉(zhuǎn)
I = imread('person.jpg');
res = flip(I,2);%左右翻轉(zhuǎn)
res1 = flip(I,1);%上下翻轉(zhuǎn)
figure,
subplot(131),imshow(I),title('原圖');
subplot(132),imshow(res),title('左右翻轉(zhuǎn)');
subplot(133),imshow(res1),title('上下翻轉(zhuǎn)');
14.3 效果分析
15?去除背景
15.1 算法原理
這個功能主要是依賴于matlab的交互式選取多邊形感興趣的區(qū)域,選取之后,對圖像未選取的部分賦值為0,具體操作是:因為roipoly函數(shù)返回了一個二進制圖像,選中的區(qū)域元素值為1,未選中的部分元素值為0,所以對圖像三個通道分別乘以這個二進制圖像,然后用cat函數(shù)實現(xiàn)三通道的合成,就得到了扣取的圖像。
15.2 算法實現(xiàn)(代碼塊)
%摳除背景
%基于提取感興趣區(qū)域扣除背景
I = app.updateImg;
g2=I;
%進行交互選擇處理區(qū)域
mask = roipoly( g2 );%roipoly函數(shù)--指定多邊形感興趣區(qū)域,將蒙版作為二進制圖像返回,所以下面的乘法就可以得到原圖像被提取的區(qū)域,因為0的部分乘以任何像素值都為0,1乘以原像
%素還是等于原像素
app.mask=mask;
x1 = immultiply( mask,g2( :,:,1 ) );
x2 = immultiply( mask,g2( :,:,2 ) );
x3 = immultiply( mask,g2( :,:,3 ) );
x = cat( 3,x1,x2,x3 );%將x1和x2和x3沿第三維度串聯(lián)起來,這里相當于三通道合并
app.Bg=x;
imshow(x,'parent',app.UIAxes),title('扣取的圖像');
15.3 效果分析
效果分析:就是這種交互式的,想要摳出比較完美的對象,很繁瑣,而且只能拉直線,扣取對象的邊緣就會很生硬,并且很多多余部分。
16?添加背景
16.1 算法原理
這個功能主要是基于上一個去除背景的功能上實現(xiàn)的,因為這個功能實質(zhì)上是圖像的疊加,所以如果背景圖小于扣取的圖像,就會報錯,所以我做了一個判斷,如果選取的背景圖片過于小,就彈出提示框,那么就只能重新選取背景圖片。然后用圖像的大小來裁剪背景圖片,以便后面圖片的加法,最后用背景圖減去扣取的圖像(利用乘法,讓扣取的人像部分像素值為0),再利用圖像的疊加,就得到了一個背景和前景的合成圖。
16.2 算法實現(xiàn)(代碼塊)
%創(chuàng)建文件選擇對話框選擇指定圖像
[file,path]=uigetfile('*.png');
bg=imread(fullfile(path,file));%讀取圖像
[M,N,~]=size(bg);
[A,B,~]=size(app.Bg);
%比較背景圖和人像圖的矩陣大小
if(M<A|N<B)
%彈出警告對話框
msgbox("當前選擇背景圖過小,請重新選擇!","警告",'non-modal');
end
%基于提取感興趣區(qū)域扣除背景
I = app.Bg;
[M,N,~] = size(I);%獲取圖片的大小
%按照圖像裁剪背景圖
bg = imcrop(bg,[0,0,N,M]);
mask=app.mask;
% figure
% imshow(bg),title('裁剪的圖像');
%用裁剪的圖像減去扣取的圖像
b1 = immultiply( ~mask,bg( :,:,1 ) );
b2 = immultiply( ~mask,bg( :,:,2 ) );
b3 = immultiply( ~mask,bg( :,:,3 ) );
b =cat(3,b1,b2,b3);
%處理之后的背景圖加上扣取的圖像
app.updateImg=b+I;
imshow(b+I,'Parent',app.UIAxes);
16.3 效果分析
效果分析:因為在處理背景和人像的疊加的時候,我是根據(jù)人像圖片的大小來裁剪的背景圖,所以背景圖總是無法顯示完整,只能顯示左上角的部分。而且背景圖必須比人像的圖片大,不然裁剪的時候,會出現(xiàn)數(shù)組越界,報錯。
- 創(chuàng)新點
人臉定位的實現(xiàn),最大連通域、膚色檢測、V-J算法
雙邊濾波進行磨皮效果的處理,有很好的保邊效果
增大眼睛,主要是基于眼睛定位,然后進行局部圖像的放大
縮小鼻翼,跟增大眼睛的原理大同小異,首先定位鼻子,然后進行局部圖像縮小
瘦臉,雖然實現(xiàn)效果很差,但是根據(jù)公式寫出來的算法,實現(xiàn)還是很成功的,可能就是需要對圓形區(qū)域每一個像素都進行一個連續(xù)的液化平移,但是沒時間去實現(xiàn)了。
- 心得體會
一開始學習這門課程,拿到教材之后,翻開書,我傻眼了,都是漢字,但是我就是看不懂。每次上完課,想拿出教材看看,看了幾頁就放棄了。到了這門課程后期,到形態(tài)學這一部分,我感覺可以用這些算法實現(xiàn)好多功能,所以在做大項目的時候,我又翻開了書,書上的代碼和算法好像沒有那么陌生了,有些算法甚至可以自己單獨寫出來了。
實現(xiàn)簡易版的美圖秀秀,我覺得首先得解決人臉定位問題,于是我開始查看相關(guān)算法,搜羅了幾天,我總結(jié)了一下,主要有四種方法:最大連通域(默認最大連通域是人臉)、膚色檢測(有很多顏色模型,教材上都有膚色的閾值范圍,我采用的YCbCr顏色模型)、V-J算法(基于haar-like的特征提取)、還有就是深度學習(沒涉及)。然后我將前三種算法,都找了20張比較清晰的人像樣本進行測試,比較他們的優(yōu)劣。毫無疑問,V-J算法效果遠勝與其他兩種,所以我就采用了matlab自帶的人臉檢測器(基于V-J算法)。然后我去看V-J算法,看了很多博文,下課之后,我又再次打開了講解V-J算法的博文,這次搞懂了百分之八九十。
然后就是人臉磨皮,我一開始只想到了在空間域和頻域的各種濾波,于是自己實現(xiàn)了一下,效果很差,五官幾乎被磨平了。不知道哪次偶然翻開教材,發(fā)現(xiàn)教材上還有一種平滑濾波--雙邊濾波,不僅考慮了像素的位置,還考慮了像素的值,位置近但是灰度值差異大,這個算法就會降低這種像素值的權(quán)重,所以就實現(xiàn)了平滑保邊的效果。于是我參照教材上的代碼寫了一遍,當然教材上是處理的灰度圖,我就只能將彩色圖的三通道分離,分別進行雙邊濾波之后,再次合成,雖然這個算法計算量很大,處理速度很慢,但是效果比其他的濾波都好。
再次就是眼部增大的功能,這個我一開始一直沒有頭緒,雖然matlab那個人臉定位可以定位眼部,但是有時候也不準確,比如定位嘴巴的時候,就會連眼睛也一起識別出來。我想,眼睛增大,實質(zhì)上不就是圖像的局部增大嘛?只要確定增大的范圍,再進行插值,就可以實現(xiàn)了,于是我開始利用matlab進行單只眼睛的定位,很好笑的是,我明明只讓它定位左眼,但是它返回了兩只眼睛的位置向量,然后我就兩只眼睛分別進行圖像增大,插值我用的是最鄰近插值,沒有用雙線性插值,這樣計算量小一些,而且效果也不差。
縮小鼻翼,這個功能是在我睡覺的時候,突然想實現(xiàn)這么一個功能,我一開始想的是等比例縮小鼻子區(qū)域,結(jié)果實現(xiàn)之后,發(fā)現(xiàn)效果很差,鼻子都歪了,因為那個算法本身也是基于像素的間隔采樣,然后線性插值,實現(xiàn)的圖像的縮小。就會把鼻子區(qū)域縮小到原鼻子區(qū)域的左上角。后來,我發(fā)現(xiàn)放大眼睛的功能不就是這樣的效果嗎?只要把放大變成縮小就可以了,所以我就改了幾行代碼,效果很快就出來了。
再次,就是瘦臉的效果,我一開始完全沒有頭緒,搜索出來的算法全部都是python語言的,然后博主的講解,我也沒搞懂。這個契機又是專業(yè)同學的那次算法講解,液化算法,雖然實質(zhì)上就是像素的平移,但是我一直沒找到逆變換的公式,因此這個算法我擱置了好久,每天都在全網(wǎng)搜索。最后,我終于看到一篇講解液化算法的文章,博主講的很清晰,雖然沒有給代碼,但是有了逆變換公式,我嘗試自己寫代碼,其實也比較簡單,先遍歷選取的圓形區(qū)域的像素,然后再確定平移之后的圓心,就可以根據(jù)逆變換公式算出變換之后對應(yīng)位置,所對應(yīng)的變換之前的像素值,然后進行雙線性插值,這個地方讓我想起大二學的《計算機圖形學》,以前還不知道這個算法有什么用,沒想到這個學期排上了用場。雖然圓形區(qū)域的像素是如愿以償?shù)钠揭屏?,但是人臉像素在移動的時候,出現(xiàn)了很大的割裂。所以,盡管這個功能我花了很多時間,但是這個功能算是失敗了。
除了每個功能的實現(xiàn),還要考慮按鈕之間的關(guān)系,怎么設(shè)置變量才能讓整個軟件流暢的運行,而不是隨便一點就報錯。我用了幾個屬性來保存變換之后的圖像,這樣處理的圖片,就能接著處理了,但是在濾鏡部分,那些效果不可能進行疊加,所以我設(shè)置了一個保存按鈕,用于用戶確認想要這個效果之后,進行效果圖的保存,然后再進行后續(xù)處理,這些讓我意識到,一個圖像處理軟件需要考慮的問題不僅僅每個功能模塊的實現(xiàn),還要根據(jù)用戶的習慣,將某些功能模塊關(guān)聯(lián)在一起實現(xiàn),而像濾鏡類似的功能模塊,則需要獨立去實現(xiàn)。
參考博客:
(37條消息) 【數(shù)字圖像處理】MATLAB實現(xiàn)圖像旋轉(zhuǎn)_Y_CanFly的博客-CSDN博客_圖像旋轉(zhuǎn)matlab
(37條消息) 積分圖算法及代碼實現(xiàn)(筆記)_molihong28的博客-CSDN博客
(37條消息) 數(shù)據(jù)挖掘領(lǐng)域十大經(jīng)典算法之—AdaBoost算法(超詳細附代碼)_fuqiuai的博客-CSDN博客_adaboost算法
(37條消息) [Matlab]簡單的人臉祛痘_ZJU_fish1996的博客-CSDN博客
(37條消息) 圖像處理算法之瘦臉及放大眼睛_grafx的博客-CSDN博客_主流大眼瘦臉 算法
(37條消息) Vision.CascadeObjectDetector-VJ算法學習_雪山飛狐W的博客-CSDN博客_vision.cascadeobjectdetector
(37條消息) Viola-Jones人臉檢測_通信程序猿的博客-CSDN博客
(37條消息) MATLAB基于CascadeObjectDetector的人臉、眼睛、鼻子、嘴巴、上半身檢測(9個模型)_Ephemeroptera的博客-CSDN博客_vision.cascadeobjectdetector
圖像變形算法:實現(xiàn)Photoshop液化工具箱中向前變形工具 - xiaotie - 博客園 (cnblogs.com)
(37條消息) MATLAB App Designer入門實戰(zhàn)(一)_slandarer的博客-CSDN博客文章來源:http://www.zghlxwxcb.cn/news/detail-422831.html
(37條消息) MATLAB 圖像處理 簡單人臉檢測(詳細,你上你也行)_Kakaluotuo的博客-CSDN博客_matlab人臉檢測文章來源地址http://www.zghlxwxcb.cn/news/detail-422831.html
到了這里,關(guān)于數(shù)字圖像處理大作業(yè)實驗報告的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!