「デジタル画像処理」
クラス: デジタル メディア テクノロジー クラス 1 (2020 年)
名前:ハッピーリトルブルー
学生ID:XXXXXXXXX
XXXX大学情報学部
目次
私はシンプルな Meitu Xiuxiu を選択し、Matlab の appdesigner を使用して機能的なインタラクティブ インターフェイスを実現しました。機能モジュールには、具体的には顔の位置決め、肌の滑らかさ、ニキビの除去、目の拡大、鼻の縮小などの顔処理機能が含まれています。
Meitu Xiuxiu と通常の学習関連アルゴリズムを主に参照して、Meitu Xiuxiu の基本バージョンを実装しましたが、通常学習しているだけではこのようなプロジェクトをサポートするには十分ではないため、実現したい機能に応じて多くの機能を参考にしました. データおよび関連コードを実装し、効果テストを実施し、コードを修正しました。
インターネット上の多くの投稿をチェックしたところ、深層学習を含まないアルゴリズムは主に 3 つあります
原理: 画像を形態学的処理することにより、複数の連結領域が形成され、最大の連結領域がデフォルトで顔が位置する領域になります。
欠陥:
1) 静止画像の場合、形態学的処理後の最大の接続ドメインが顔の一部ではない場合があるため、このアルゴリズムには比較的大きな制限があります。
2) 画像内の顔は 1 つだけ検出できます
原理: 肌の色を検出するには多くの方法がありますが、異なる色空間に基づくか、異なる肌の色モデルに基づくかに関係なく、基本的な開始点は肌の色の分布を集約することです。つまり、肌の色の成分は通常、特定の範囲内に集まります。 。色空間が異なれば、肌の色の分布範囲も異なります。
1) RGB色空間
統計によると、均一な光の下では、肌の色の分布範囲は次のとおりです: R>95、G>40、B>20、最大{R,G,B}-最小{R,G,B}>15、| RG| >15 および R>G および R>B
2) YCbCr色空間
統計によると、YCbCr 色空間における肌色の分布範囲は 77<=Cb<=127,133<=Cr<=173 です。以下は肌の色に基づく顔検出に使用される色空間であり、肌色モデルはガウス モデルを選択せずに、しきい値モデルを使用します。
3) HSV色空間
HSV 空間で確立された肌色検出モデルは、0 度<H<=25 度または 335 度<=H<=360 度、0.2<=S=0.6 および 0.4<=V の要件を満たす必要があります。
欠陥:
- 画像の背景や人物の服装が肌の色と似ている場合、ターゲティングは不正確になります。
- フィルターを追加したポートレート写真の中には、肌色のピクセルを検出できないものもあります。
Cascaded Object Detector は、Viola-Jones アルゴリズムを使用して、人の顔、鼻、目、口、または上半身を検出します。Image Labeler を使用して、この System object で使用するカスタム分類子をトレーニングすることもできます。このツールは顔の位置を比較的正確に特定でき、口、鼻、目を簡単に特定でき、1 枚の写真内に複数の顔を見つけることができます。
このツールで使用されているアルゴリズムは比較的複雑ですが、インターネットで読んだブログ投稿によると、おおよその理解はできました。概要は次のとおりです。
この検出器で使用されるアルゴリズムは VJ アルゴリズムです。このアルゴリズムは、このアルゴリズムを提案した 2 人の著名人、Viola と Jones にちなんで名付けられました。要は、AdaBoostアルゴリズムに基づいて、Haar-likeウェーブレット特徴(haar特徴と呼ぶ)と積分マップ法を用いて顔検出を行うということである。まず、AdaBoost アルゴリズムを見てみましょう。このアルゴリズムは、基本的に複数の弱分類器を組み合わせて 1 つの強分類器にします。
- N 個のサンプルがあると仮定してサンプルを初期化し、各サンプルの重みは最初は 1/N です。
- 分類器をトレーニングします。分類プロセス中にサンプルが陽性サンプルとして分類された場合、つまりサンプル分類が正確な場合、次の分類反復で陽性サンプルの重みが減ります。負のサンプルの場合、重みを増やして N 回反復して、サンプル分類の誤差関数の値を最小化する分類器を取得します。これにより弱分類器が取得され、複数の弱分類器を組み合わせて強分類器が取得されます。
では、AdaBoost のトレーニング サンプルはどこから来たのでしょうか? 次に、Haar のようなウェーブレット特徴について話さなければなりません。見た目は人それぞれ異なりますが、人間の顔には、暗い目や鼻など、いくつかの固定された特徴があります。顔は比較的暗いですが、中央部分は頬よりも明るく、口の部分も暗く、これらの特徴に従って、VJ は 4 つの長方形特徴を使用し、黒い部分のグレー値から白い部分のグレー値を減算して人間の顔を生成します。 。24*24 の画像には 160,000 個の特徴長方形があり、これらの特徴長方形内のすべてのピクセルを 1 回走査して合計すると計算量が非常に多くなり、このとき積分マップが表示されます。
積分グラフは、位置 (i, j) のピクセルの積分が左上のすべてのピクセルの合計であることを特徴とし、いくつかのピクセルの積分を知っていて、特定の領域のピクセルの合計を求めることができれば、いくつかの単純な追加を実行する必要があります。ただし、毎回トラバースする必要はありません。したがって、写真では各画素を整数で表し、その積分値を元の画像と同じサイズの行列に格納し、指定した領域内の画素の和を計算するときは、積分値を求めるだけで済みます。加算、減算する位置に対応する を入力することで、この領域の画素和を求めることができ、計算量が大幅に削減されます。
欠点:口ではない部分が配置されたり、目が口として配置されたりする場合があります。
一般に、効果の順序は、VJ アルゴリズム > 最大接続ドメイン > 肌の色検出です。
1 つ目は、最も接続されているドメインを検出する顔検出コードです。
最も接続されている領域の検出
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);%结构元素
BW = -imerode(BW,B) + BW;
% BW=imdilate(BW,B)-imerode(BW,B);
% figure,imshow(BW),title('形态学边界提取')
BW = bwmorph(BW,'thicken');
% figure,imshow(BW),title('加粗边界')
BW = ~(bwareaopen(~(BW), 50));%使用bwareaopen 函数删除包含的像素数少于50的对象
% figure,imshow(BW),title('把空洞填了')
%进行形态学运算
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);%%将数据载入gpu可以加速,电脑不一定支持
%最小化背景
%细分
div = 10;
r = floor(n1/div);%分成10块 行
c = floor(n2/div);%分成10块 列
x1 = 1;x2 = r;%对应行初始化
s = r*c;%块面积
%判断人脸是否处于图片四周,如果不是就全部弄黑
for i=1:div
y1 = 1;y2 = c;%对应列初始化
for j=1:div
loc = find(BW(x1:x2,y1:y2)==0);%统计这一块黑色像素的位置
num = length(loc);
rate = num*100/s;%统计黑色像素占比
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函数对8连通域区间进行标号
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('人脸检测')
2 つ目は、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 图像的红色、绿色和蓝色值转换为 YCbCr 图像的亮度 (Y) 和色度(Cb 和 Cr)值。
Y = YCbCr(:,:,1);
Cb = YCbCr(:,:,2);
Cr = YCbCr(:,:,3);
pic_gray = zeros(ROW,COL);%创建和原图大小相同的全零矩阵
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('形态学滤波');
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('头像检测');
3 番目は、MATLAB ツールを使用して顔の位置を特定することです。
コードブロック:
detector = vision.CascadeObjectDetector;%获取检测器
%Read the input image
I = imread('person.jpg');%读入图像
face_dtect = step(detector,I);%人脸检测,返回人脸区域的位置向量
figure
imshow(I)%显示图像
hold on
for i = 1:size(face_dtect,1)%检测器可能检测到多个
rectangle('Position',face_dtect(i,:),'LineWidth',1,'LineStyle','-','EdgeColor','m');%用矩形标注出人脸区域
end
title('人脸检测');
肌の色の検出:
結果分析:
この効果は、背景と人物の服が肌色のしきい値に近くない画像の場合に優れていますが、特に顔の領域が小さい場合や、人の服が背景や肌に近い場合、ほとんどのテスト画像の位置は正確ではありません。色の閾値、効果 ただ悪い。
最大接続ドメイン:
結果分析: 最大の接続ドメインのデフォルトは、画像全体の最大の接続ドメインは顔であるため、画像内の顔の割合が大きい写真では処理効果が非常に優れています (大きいほど良いので、顔は次のようになります)できるだけ完全に)、しかし、最初の 2 つの写真のように、少女全体が遠くに立っているのと、彼女は横に立っているのですが、顔の部分に大きな切れ目があり、接続することができないため、検出結果は完全に不完全です間違い。しかし、一般に、テスト効果が成功する確率は、肌の色検出の確率よりもはるかに優れています。
VJアルゴリズム:
結果分析:
このアルゴリズムは顔の位置を比較的正確に特定し、顔の特徴や上半身の位置を特定することもできます。正面顔の画像の精度は高く、顔の部分は比較的小さくてもかまいませんが、完全なものでなければなりません。上の最後の 2 枚の写真の位置合わせに失敗しました。最後から 2 番目の写真は 2 つの顔を見つけました。登場人物の服は構造が複雑です。検出器もそれを顔とみなしました。最後の写真は顔を直接検出しませんでした。誤差を比較しました。」顔の特徴をテストしていたとき、検出器が口を検出すると目にマークが付くことが多いですが、鼻の検出の方が正確であることがわかりました。ただし、全体的な効果は前の 2 つのアルゴリズムよりもはるかに優れています。
マイクロダーマブレーション: 本質的には画像の平滑化です。学習された画像を平滑化するための現在のアルゴリズムによると、空間領域ではガウス フィルター、メディアン フィルター、平均フィルターがあり、周波数領域ではローパス フィルターがあります。テスト中に、このフィルターは顔の特徴や境界線をぼかし、その効果が理想的ではないことがわかりました。教科書を読んでみると、教科書では顔を滑らかにするためにバイラテラルフィルターが使用されていることがわかりました。本の公式を読んだ後、私の頭はめまいを感じましたが、Liu Longhao 氏の説明を聞いた後、このアルゴリズムは難しくないことがわかりました。
このアルゴリズムはガウス フィルタリングを改良したもので、ガウス フィルタリングはピクセル値に対する位置の影響のみを考慮するため、位置が近いほどピクセル値への影響が大きくなるため、境界などの重要な情報がぼやけてしまいます。バイラテラル フィルタリングでは、位置とピクセル値が同等に重要であると考えられ、平坦な領域ではピクセルの位置がバイラテラル フィルタリングの効果を支配します。エッジ領域では、エッジの両側のピクセル値が大きく異なるため、エッジの反対側のピクセルの重みが軽減され、エッジのこちら側のピクセルにほとんど影響を与えません。エッジ保存の効果。
%用双边滤波实现人脸美化的效果
I = imread('person2.jpg');%读取图像
figure(1)
imshow(I),title('原图');%显示原图
bfilt_rgb(I,15,6,0.1);%调用双边滤波函数,进行滤波处理
%函数实现
function g = bfilt_rgb(f,r,a,b)
% f彩色图;r滤波半径;a全局方差;b局部方差
[x,y] = meshgrid(-r:r);%创建二维网格坐标
w1 = exp(-(x.^2+y.^2)/(2*a^2));%计算滤波内的空间权值
f = im2double(f);%将uint8转换成double,方便后续处理
h = waitbar(0,'Applying bilateral filter...');%设置进度条
set(h,'Name','Bilateral Filter Progress');
detector = vision.CascadeObjectDetector;%目标探测器
facePart = step(detector,f);
%获取脸部坐标
X_min = facePart(1,1);%人脸区域的左下x坐标
Y_min = facePart(1,2);%y坐标
Width = facePart(1,3);%区域宽度
Height = facePart(1,4);%区域高度
%三通道分离
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)));%创建三个和原图像大小相同的全零矩阵
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);%三通道的滤波区域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));%求滤波内每个像素对目标像素的影响权值(基于像素值)
w = w1.*w2;%将两种权值相加,求得滤波范围内每个像素的最终权值
gr(i-r,j-r) = sum(sum(temp1.*w))/sum(w(:));%将权值与对应像素值相乘相加,再除以权值和,即求得该像素点经双边滤波后的像素值
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);%串联数组,合并三通道
result=imadd(g,f);
figure(2)
imshow(result),title('双边滤波');%显示处理图
end
効果分析: 双方向フィルタリングは肌を滑らかにするだけでなく、顔の特徴も保持します。効果は非常に優れていますが、処理速度は遅くなります。
1 つ目は、MATLAB ツールボックスの顔検出器を使用して 2 つの目の位置ベクトルを検出し、次に 2 つの目にそれぞれズームインします。まず、各目の位置ベクトルに従って拡大領域の中心座標を決定します。拡大領域の辺の長さを設定し、拡大する領域をトラバースし、最近傍補間法を使用して拡大されたピクセル値を取得し、トラバースが完了すると、拡大効果が実現されます。
%放大眼睛
I = imread('person13.jpg');%读入图像
I = im2double(I);%数据类型转化,以便后续处理
%V-J算法检测眼睛
detector = vision.CascadeObjectDetector;%调用检测器
detector.ClassificationModel='LeftEyeCART';%调用眼睛检测器
bboxes = detector(I);%检测眼睛,返回眼睛区域的位置向量
%放大眼睛
strength=20;%放大强度
pointx=floor(bboxes(1,2)+(bboxes(1,3)/2));%根据检测器大致确定眼睛中心点
pointy=floor(bboxes(1,1)+(bboxes(1,4)/2))+10;
r=50;%放大区域边长
left=pointy-r;
right=pointy+r;
top=pointx-r;
bottom=pointx+r;
space=r*r;%放大的正方形区域
I1=I;%将原图缓存,存储处理后的图像
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);%放大后的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('原图');
効果分析: この機能は主に人間の目の位置認識に基づいているため、人間の目の位置の位置の正確さが目の拡大機能の実現効果に直接影響します。ポートレートによっては、目が検出できない場合もあるため、これは基本的なものです。この機能は使用できず、ポートレートによっては口の部分を目の部分として認識してしまうため、口の部分が拡大されてしまいますが、目の位置が正確であれば処理効果は非常に良好です。
このアルゴリズムは依然として顔検出 VJ とエリア ズーム アルゴリズムに基づいており、手順は目のズームと似ています。最初に matlab を使用して鼻の位置を特定し、次にツールから返された位置ベクトルに従って鼻の中心座標を決定し、最後に領域拡大アルゴリズムを使用しますが、次の効果を達成するために強度を負の数に変更します。面積縮小、つまり鼻縮小手術です。
%瘦鼻
I = imread('person25.jpg');
detector = vision.CascadeObjectDetector;%检测器
detector.ClassificationModel='Nose';
detector.MergeThreshold=10;%增加合并阈值
bboxes=detector(I);
Nose=insertObjectAnnotation(I,'rectangle',bboxes,'Nose');%用矩形框标出鼻子定位的矩形区域
figure(9);imshow(Nose);title('Nose'); %显示图像
%区域图像缩小
strength=-20;%缩小强度
pointx=floor(bboxes(1,2)+(bboxes(1,3)/2));%根据检测器大致确定鼻子中心点
pointy=floor(bboxes(1,1)+(bboxes(1,4)/2));
r=50;%放大区域边长
left=pointy-r;
right=pointy+r;
top=pointx-r;
bottom=pointx+r;
space=r*r;%缩小的正方形区域
I1=I;%将原图缓存,存储处理后的图像
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);%放大后的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);
効果分析:この機能は目を拡大するのとほぼ同じであるため、鼻の位置が正確である限り、鼻翼の縮小効果は非常に優れていますが、鼻の位置が定まっていないポートレートの場合は縮小できず、鼻が小さくなり、目が視覚的に大きくなる効果があることが判明した魔法を見つけました。
このアルゴリズムは主にピクセル変換に基づいています。インターネット上の液状化アルゴリズムに関する投稿を参照しましたが、逆変換式とアルゴリズムの実装手順は示されていますが、実装コードは示されていません。したがって、理解できませんでした。このアルゴリズムを最初は深く理解していて、当時は実装するためのコードを書くことができませんでしたが、後でもう一度アルゴリズムを見てみると、このアルゴリズムは実際にはピクセル変換であることがわかりました。 、変換式に従って計算された座標は倍精度であり、画像行列の座標は正の整数であるため、変換時にどのような補間アルゴリズムが使用されても、ピクセルの重複やピクセル値の欠落の問題が発生する可能性があります。したがって、逆変換は、元の位置とターゲット位置のピクセルの位置を逆にするために使用されます。逆変換も倍精度であるため、元のピクセル値の隣接ピクセルに対して双一次補間アルゴリズムが使用されます。計算されたピクセル値は目的位置のピクセル値であるため、ピクセルの比較的スムーズな変換が達成されます。アルゴリズムを実装した後、円形領域のインタラクティブな選択を使用して、変換中心を選択します。目的は、顔を薄くする効果を視覚的に達成するために、顔の端のピクセルを滑らかに変換することです。しかし、実際に操作してみると、選択範囲と対象円の中心との距離が離れすぎると歪みが生じ、顔が大きく変形してしまいます。良い効果ですが、ピクセルの目立たない移動を何度も行う必要があります。より明らかなフェイスリフト効果が見られます。どうやって完璧に仕上げるか考えたのですが、時間がなさそうなので断念しました。
for cou =1:300
if cou==1
I = imread('C:\Users\leishen\Desktop\数字图像处理\期末大作业\测试效果\person7.jpg');%读入图片
else
I = imread('C:\Users\leishen\Desktop\数字图像处理\期末大作业\测试效果\person25.jpg');%读入修改之后的图片,以便继续进行瘦脸处理
end
figure
imshow(I);
h = drawcircle('Color','k','FaceAlpha',0.4);%交互式选取圆形区域
M = ginput(1); %交互式选取坐标,即变化后的圆心的位置
[m,n,~] = size(I);%图像矩阵的大小
center = [floor(h.Center(2)),floor(h.Center(1))];%变形前的圆心
radius = h.Radius;%变形的圆半径
RGB_buff = I;
%遍历圆形选区的每一个像素
for i=1:m
for j=1:n
distant = sqrt((i-center(1)).^2+(j-center(2)).^2);%判断该像素点是否在选取的圆形区域内
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);%舍弃小数部分,保留整数
ab = U-uu;%这个数据用于后面双线性插值处理
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('是否要继续调整', ...
'选择', ...
'YES','NO','NO');
switch answer
case 'YES'
imwrite(I,'C:\Users\leishen\Desktop\数字图像处理\期末大作业\测试效果\person25.jpg');
case 'NO'
msgbox("退出调整");
break;
end
end
顔の左側は大きなピクセル移動効果を実現していることがわかり、視覚的には顔を薄くする効果がありますが、よく見るとピクセル移動により局所的な歪みやぼやけが発生していることがわかります。画像。
この実装原理は比較的単純で、まずニキビを除去したい領域を対話的に選択し、その領域の左上隅の最初のピクセルを抽出し、-5 ~ +5 の範囲のピクセル値をランダムに使用します。選択範囲を塗りつぶします。次に、塗りつぶされた境界を弱めるために、ガウス フィルタリングを使用して面をガウス フィルタリングで処理します。
g=imread('person1.jpg');
% n 为操作次数,默认为1,g为原图
n=3;
g2 = g;
%得到原图像的大小
[ M,N,~ ] = size( g );
while( n ~=0 )
n = n - 1;
%进行交互选择处理区域
mask = roipoly( g2 );%roipoly函数--指定多边形感兴趣区域,将蒙版作为二进制图像返回,所以下面的乘法就可以得到原图像被提取的区域,因为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沿第三维度串联起来,这里相当于三通道合并
% figure
% imshow(x);%原来x是交互时提取的区域
%预分配内存,f1,f2,f3存储三个通道的运算结果
f1 = zeros( M,N );
f2 = zeros( M,N );
f3 = zeros( M,N );
%跳出双重循环设置flag
flag = 0;
%找到第一个像素值不为0的点,得到该点像素值,作为采样后填充的像素
for i = 1:M
for j = 1:N
if( x1( i,j ) ~= 0 )
r = x( i,j,: );
flag = 1;%找到之后,跳出循环
break
end
if( flag == 1 )
break
end
end
end
%随机产生填充图像,这就是填充痘印部分的图像
y = zeros(3,3,3);
y( :,:,1 ) = randi([r(1)-5,r(1)+5],[3,3]);%取像素值-5到像素值+5的范围的随机数组成一个3X3的矩阵
y( :,:,2 ) = randi([r(2)-5,r(2)+5],[3,3]);
y( :,:,3 ) = randi([r(3)-5,r(3)+5],[3 3]);
%类型转换
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 );
%类型转换
f = uint8( f );
%得到处理后图像,居然可以直接加减,那还学什么运算函数
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('填充处理后图像');
結果分析: ニキビ除去領域のピクセルは、領域の左上隅の最初のピクセル +5 ~ 5 の範囲に従ってランダムに塗りつぶされるためです。ニキビが顔の角まで成長すると、塗りつぶし効果が非常に急激であることがわかります。平らな領域であっても、顔と塗りつぶし領域がうまく接続されておらず、塗りつぶし領域はかなり急です。ガウスフィルタリングが実行され、効果はまだ平均的ですが、ハイライトのない顔の場合、ニキビを除去する効果は良好であるはずです。
本質的には、これはテクスチャ抽出プロセスです。まず、3 つのチャンネルを分離し、処理するチャンネルを選択し、このチャンネルを反転してから、ガウス フィルターを使用してネガ フィルムをフィルターし、ノイズを除去します。最後に、ポジ フィルムとネガフィルムが重ね合わされ、最終的な正規化の後、より理想的なスケッチ効果が得られます。
I = imread('person11.jpg');
[height,width,~]=size(I);%获取图像矩阵的大小
N=zeros(height,width);%创建两个全零矩阵
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 = 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
%模糊程度越高,得到的素描结果越清晰,框架纹理颜色越深
figure
subplot(121),imshow(out/255);%归一化处理并显示图像
subplot(122),imshow(I);
効果分析: この処理は主にテクスチャを抽出し、スケッチのような効果を実現するため、画像が鮮明であるほど効果が高くなります。
長方形のウィンドウを定義し、このウィンドウを使用して画像の各ピクセルを横断し (3 つのチャネルが個別に処理されます)、長方形内の各ピクセルのグレー値を計算し、この領域内の最大のピクセル値を現在のピクセル値として取得します。シンプルな油絵効果を実現します。
A=imread('person4.jpg');
% 油画效果
%创建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);%记录最大值和最大值对应的位置
Image(i,j,v)=pos-1;%将最大值赋值给当前的像素
end
end
end
figure
subplot(121),imshow(Image);
subplot(122),imshow(A);
効果分析: ウィンドウが大きいほど、効果はより明白になりますが、最大値が取られるため、一部の場所での突然の変化が非常に突然で、効果はあまり理想的ではありませんが、基本的に油絵効果が達成されます。
まず処理ウィンドウを作成し、サイズをカスタマイズします。次に、このウィンドウを使用して画像の各ピクセルをスライドし、このウィンドウのピクセルをランダムに選択し、それを現在スライドしているピクセルに割り当てます。すべてのピクセルが通過するまで、すりガラス効果が得られます。完成しました。
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,:);%将图像对应像素值赋值给窗口
x2=ceil(rand(1)*m);%从窗口像素随机挑选一个像素,因为坐标必须为正整数,所以用ceil四舍五入为整数
y2=ceil(rand(1)*n);
Image(i,j,:)=mymask(x2,y2,:);%将选出的像素值赋值给当前的像素
end
end
imshow(Image);%显示图像
この効果の実現は比較的簡単で、本質的には、画像の境界を抽出し、その境界を強調表示することです。具体的な手順としては、グレースケール画像に対してソーベルフィルタリングを実行し、境界を抽出してグレースケール変換を実行します。
img=imread('building2.jpg');%读入图像
f0=rgb2gray(img);%改为灰度图像
f1=im2double(f1);
h2=fspecial('sobel'); %进行sobel滤波
g3=filter2(h2,f1,'same');
K=mat2gray(g3); %将矩阵转换成灰度图
figure
imshow(K);
効果分析:レリーフ効果は境界抽出の効果に依存するため、グレー値の変化が大きい画像は処理効果が良く、建物などの画像ではこの効果は悪くないので、処理した画像を掲載しました建物も
本質的には、これは行列の回転です。回転軸は画像の中心です。画像の各座標が回転公式によって回転された座標を計算しますが、計算された座標は浮動小数点数であり、座標はは正の整数であるため、四捨五入する必要がありますが、四捨五入後、一部の座標のピクセル値が重なったり、一部の座標でピクセルが存在しない可能性があるため、変換後の座標を使用して変換前の座標を決定し、次に、変換前の座標に近いピクセルが単純な線形補間に使用され、変換された座標のピクセル値が計算され、画像を走査した後、回転された画像が取得されます。
%图像旋转
I = imread('person10.jpg');%读入图像
I = im2double(I);
I2=imrotate(I,-22);
figure
subplot(121),imshow(I2),title('顺时针旋转22度');%调用函数实现
%自己写代码实现
%旋转22度
a = 22/180*pi;%角度转换成弧度
Rotate = [cos(a) -sin(a);sin(a) cos(a)];%旋转变换矩阵
[m,n,~] = size(I);%矩阵大小
center = [m,n]/2;%旋转轴中心
% 计算显示完整图像需要的画布大小
hh = floor(m*sin(a)+n*cos(a))+1;
ww = floor(m*cos(a)+n*sin(a))+1;
c2 = [hh; ww] / 2;%旋转之后的轴中心
res = zeros(size(I));%创建存储结果的全零矩阵
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('顺时针旋转变化22');%显示图像
回転を実現するセルフプログラミング機能には、画像が引き伸ばされたり、画像が不完全に表示されたりするなどの問題があり、アルゴリズムの実装にはまだ課題がいくつかあります。
インタラクティブ関数を使用してトリミングされた領域を抽出し、返されたパラメーターに従ってトリミングされた画像を表示します。
%交互式裁剪图像
I =imread(‘person.jpg’);%读取图像
[J,rect] = imcrop(I);调用函数交互式裁剪图像,J返回的是裁剪的区域,rect返回的是指定裁剪区域的四元素位置向量。
I2 = imcrop(I,rect);%根据返回的位置向量裁剪图像并返回
imshow(I2);%显示裁剪的图像
効果分析:インタラクティブカットの実現です。
Matlab 関数 fspecial を使用して、モーション変位パラメーターと変位角度パラメーターを設定してモーション シミュレーション フィルターを取得し、そのフィルターを使用してイメージをフィルター処理して、モーション ブラー イメージを取得します。
%运动模糊
I = imread('buiding1.jpg');%读入图像
len=20;%设置运动位移为20个像素
theta=50;%设置运动角度为45度
psf = fspecial('motion',len,theta);%建立二维运动仿真滤波器psf
j = imfilter(I,psf,'circular','conv');%用滤波器产生退化图像
figure
subplot(121),imshow(j),title('运动模糊');%显示运动模糊图像
subplot(122),imshow(I),title('原图');%显示原图像
画像の反転は本質的に行列上の要素シーケンスの反転です. 反転する必要がある画像 I のみがある場合、反転関数はデフォルトで各列と行の要素シーケンスを反転します. 次元を追加する場合1 を後ろにすると、各列が反転します。各行の要素シーケンスは上下反転の効果を実現します。後ろに次元 2 を追加すると、各行の要素シーケンスが反転し、左右反転の効果が得られます。気がついた。
%图像翻转
I = imread('person.jpg');
res = flip(I,2);%左右翻转
res1 = flip(I,1);%上下翻转
figure,
subplot(131),imshow(I),title('原图');
subplot(132),imshow(res),title('左右翻转');
subplot(133),imshow(res1),title('上下翻转');
この関数は主に matlab の多角形の関心領域の対話型選択に依存しています。選択後、画像の選択されていない部分には値 0 が割り当てられます。具体的な操作は次のとおりです: roipoly 関数はバイナリ イメージを返すため、選択された領域の要素値面積は 1 です。要素の選択されていない部分の値は 0 であるため、画像の 3 つのチャネルにバイナリ画像が乗算され、cat 関数を使用して 3 つのチャネルの合成が実現され、差し引かれます。画像が得られます。
%抠除背景
%基于提取感兴趣区域扣除背景
I = app.updateImg;
g2=I;
%进行交互选择处理区域
mask = roipoly( g2 );%roipoly函数--指定多边形感兴趣区域,将蒙版作为二进制图像返回,所以下面的乘法就可以得到原图像被提取的区域,因为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沿第三维度串联起来,这里相当于三通道合并
app.Bg=x;
imshow(x,'parent',app.UIAxes),title('扣取的图像');
効果分析: この種のインタラクティブです。より完璧なオブジェクトを切り出すのは非常に面倒で、直線しか引くことができません。演繹オブジェクトのエッジは非常に硬く、冗長な部分が多くなります。
この機能は主に前述の背景を削除する機能に基づいています。この機能は基本的に画像を重ね合わせるため、背景画像が差し引かれた画像より小さい場合はエラーが報告されます。選択した背景 画像が小さすぎる場合は、プロンプト ボックスが表示され、背景画像を再度選択することしかできません。次に、後続の画像の追加を容易にするために、画像のサイズを使用して背景画像をトリミングし、最後に背景画像から差し引かれた画像を減算します (乗算を使用して、差し引かれたポートレート部分のピクセル値を 0 にします)。画像を重ね合わせて背景と前景の合成画像を取得します。
%创建文件选择对话框选择指定图像
[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
%基于提取感兴趣区域扣除背景
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);
効果分析:背景とポートレートのオーバーレイを扱う場合、ポートレート画像のサイズに合わせて背景画像をカットするため、背景画像が常に完全に表示されるわけではなく、左上隅の部分のみが表示されます。さらに、背景画像はポートレート画像より大きくなければなりません。そうでないと、トリミング時に配列が範囲外になり、エラーが報告されます。
双方向フィルタリングを使用してスキンスムージング効果を処理し、優れたエッジ保護効果をもたらします。
主に目の位置に基づいて目を拡大し、部分画像を拡大します
鼻翼の縮小は目を拡大する原理と似ており、まず鼻の位置を決めてから部分画像を縮小します。
フェイスリフト、実装効果は非常に低いですが、公式に従って書かれたアルゴリズムは依然として非常に成功しています。円形領域内の各ピクセルに対して連続的な液状化変換を実行する必要があるかもしれませんが、実装する時間がありませんそれ。
このコースを学び始めた当初、教材を手に入れて本を開いたのですが、漢字ばかりで全く理解できませんでした。授業が終わるたびに教科書を取り出して読みたかったのですが、数ページ読んだだけで諦めていました。このコースの後半、形態学の部分で、これらのアルゴリズムを使用して多くの機能を実現できると感じたので、大きなプロジェクトに取り組んでいたときに、もう一度本を開きました。この本はそれほど奇妙ではないようで、いくつかのアルゴリズムはそれ自体で書き出すこともできます。
Meitu Xiuxiu の簡易バージョンを実現するには、まず顔の位置の問題を解決する必要があると思い、関連するアルゴリズムを確認し始め、数日間検索してまとめました。主な方法は 4 つあります。ドメイン(人間の顔です)、肌の色の検出(多くのカラーモデルがあり、肌の色の閾値範囲は教科書に載っていますが、私はYCbCrカラーモデルを使用します)、VJアルゴリズム(haar様の特徴抽出に基づく)、および深層学習 (関与していません)。次に、最初の 3 つのアルゴリズムを 20 個の鮮明なポートレート サンプルでテストし、その長所と短所を比較しました。VJ アルゴリズムが他の 2 つよりもはるかに優れていることは疑いの余地がないため、MATLAB に付属する顔検出器 (VJ アルゴリズムに基づく) を使用しました。それからVJアルゴリズムを見に行ったり、ブログ記事をたくさん読んだり、授業が終わった後にもう一度VJアルゴリズムを説明しているブログ記事を開いたりして、今度は8割から9割くらい理解できました。
次に顔の肌のリサーフェシングですが、最初は空間領域と周波数領域での各種フィルタしか考えていなかったので、自分で気づきましたが、効果は非常に低く、顔の特徴はほぼ滑らかになりました。いつ偶然教科書を開いたのかわかりませんが、教科書に平滑化フィルタ、つまりピクセルの位置だけでなくピクセルの値も考慮するバイラテラルフィルタリングがあることを知りました。は近いですが、グレー値の差が大きい場合、このアルゴリズムはこのピクセル値の重みを減らすため、滑らかなエッジ保存の効果が得られます。ということで教科書のコードを参考に書きました もちろん教科書はグレースケール画像を処理したものです カラー画像の3チャンネルを分離し、それぞれバイラテラルフィルタリングを行って再度合成するしかありません このアルゴリズムですが計算量が多く、処理速度は非常に遅いですが、効果は他のフィルターよりも優れています。
3つ目は目を拡大する機能ですが、これについては最初は全く知りませんでした、MATLABの顔の位置合わせでは目の位置は特定できますが、口の位置を合わせると目も一緒に認識されてしまうなど不正確な場合があります。目の拡大というのは本質的には画像の局所的な拡大ではないでしょうか?増加した範囲を決定して補間すれば実現できるので、MATLAB を使用して片目の位置を特定し始めました。左目だけを特定させたのに、2 つの位置が戻ってくるのは面白いです。目の位置ベクトルを取得して、両目の画像を別々に拡大していますが、バイリニア補間ではなく最近傍補間を使っているので計算量も少なく、効果も悪くありません。
鼻翼を小さくする機能は、寝ているときにふと実現したいと思い、最初は比例して鼻の部分を小さくすることを考えていましたが、実現してみると効果が非常に悪いことが分かり、アルゴリズム自体もピクセルベースの間隔サンプリングと線形補間によって画像の縮小を実現するため、鼻が曲がっています。鼻領域は、元の鼻領域の左上隅まで縮小されます。後で知ったのですが、目を大きくする機能は同じ効果ではないのですか?ズームインをズームアウトに変更するだけなので、数行のコードを変更したところ、効果がすぐに現れました。
繰り返しになりますが、顔痩せの効果なのですが、最初は全く分かりませんでしたし、検索したアルゴリズムもPython言語ばかりで、ブロガーさんの説明も分かりませんでした。この機会に、Liu Longhao 氏によるアルゴリズムの説明が行われました。液状化アルゴリズムは基本的にピクセルの変換ですが、逆変換の公式を見つけたことはありません。そのため、このアルゴリズムを長い間保留にして、ネットワーク全体を検索しました。毎日。ようやく液状化アルゴリズムを説明した記事を見つけました。ブロガーさんは非常にわかりやすく話していました。コードは与えられていませんでしたが、逆変換式を使って自分でコードを書いてみました。実際、比較的簡単です。まず、 、選択した円形領域のピクセルを横断し、変換後の円の中心を決定します。逆変換公式に従って変換後の対応する位置と、変換前の対応するピクセル値を計算して、双一次補間を実行できます。この場所は 2 年生の「コンピュータ グラフィックス」を思い出させます。私はこれまでこのアルゴリズムの使い方を知りませんでしたが、今学期役立つとは予想していませんでした。円形の領域内のピクセルは期待どおりに変換されますが、顔のピクセルが移動すると、大きな分割が発生します。ということで、この機能には多くの時間を費やしましたが、この機能は失敗でした。
各機能の実現に加えて、ランダムにエラーを報告するのではなく、ボタン間の関係、ソフトウェア全体がスムーズに動作するように変数を設定する方法なども考慮する必要があります。変換後の画像をさらに加工できるように、いくつかの属性を使用して変換した画像を保存しましたが、フィルター部分ではそれらの効果を重ね合わせることができないため、ユーザーが希望の効果を確認できるように保存ボタンを設定しました。 、エフェクト画像を保存し、その後の処理を行うということは、画像処理ソフトウェアが各機能モジュールの実現だけでなく、ユーザーの習慣に合わせて実現することも考慮する必要があることを実感させられました。一方、フィルタなどの機能モジュールは個別に実装する必要があります。
参考ブログ:
(メッセージ数 37 件) [デジタル画像処理] MATLAB で画像回転を実現_Y_CanFly のブログ-CSDN ブログ_画像回転 matlab
(37 メッセージ) 積分グラフ アルゴリズムとコード実装 (メモ)_molihong28 のブログ - CSDN ブログ
(メッセージ 37 件) [Matlab] 簡単な顔のニキビ除去_ZJU_fish1996 のブログ - CSDN ブログ
(メッセージ数 37 件) 顔痩せと目を大きくするための画像処理アルゴリズム
(メッセージ数 37) Viola-Jones の顔検出_コミュニケーション プログラム Ape のブログ - CSDN ブログ
(メッセージ 37 件) MATLAB App Designer 入門 (1) - 誹謗中傷者のブログ - CSDN ブログ
(メッセージ数 37) MATLAB 画像処理による簡単な顔検出 (詳細、あなたもできます)_Kakaluotuo のブログ - CSDN ブログ_matlab 顔検出