✅ 大三下时弄的


文章目录

  • 最终效果图
  • 摘要
  • 1 研究背景及意义
  • 2 基本原理描述
  • 3 实验数据来源
    • 3.1 原始图像的来源
    • 3.2 天空背景图像的来源
  • 4 实验步骤及相应处理结果
    • 4.1 原始图像的预处理
    • 4.2 区域生长法分割图像
    • 4.3 形态学处理填充孔洞
    • 4.4 边缘检测+根据二值图像构造RGB图像
    • 4.5 图像拼接
    • 4.6 图像整体融合
    • 4.7 边缘处理
  • 5 实验结果分析
  • 6 总结与心得体会
  • 7 完整代码
  • 8 补充说明及下载链接

最终效果图


注: 鼠标点击,选完 “点” 后,需要再按一下 “回车”。


摘要

● 本次从日常生活的实际需要出发,主要研究了图像的分割转换及重组部分与原图像的融合,基于区域生长法和形态学处理的方法可以将图像的背景转换为其他想要替换的图片,并通过边缘融合等方法将转换后的背景与原图像进行调整,减轻违和感以达到更好的显示效果。相比于人工手动抠图的方法,这种处理方法更加方便简洁,极大地简化了修图的繁琐步骤,学习基础低,容易上手使用,并且大大缩短了同类型修图的时间,处理速度较快,故而可以广泛应用于日常的照片处理。


1 研究背景及意义

● 在生活中,人们通常使用摄影来记录自己的各种日常,拍照已经成为生活里不可缺少的重要组成部分,融入了每个人的每个生活场景与欢声笑语,每张照片都有其特定的含义,传递着每个人的情感。可是有时候天气不好,拍出来的照片常常会因为背景昏暗、色调阴沉而不够美观,就譬如去景区旅游的时候,如果当天是阴天或者雨天,照片中的天空就是灰蒙蒙的,整张图片也会显得暗淡,这种情况难免会让人觉得可惜。

● 本次研究了一种自动处理图像的方法,可以将拍摄于阴雨天的照片中灰蒙蒙的天空转换成蓝天白云、夕阳西下或者是彩虹以及其他想要的背景,并将整体的色调调整成更明亮的显示效果。这种技术的操作十分简单上手,处理速度较快,可以很成功地对照片进行背景转换,同时优化整合两部分内容,使得处理后的图片看起来更加和谐,视觉效果增强,极大地省略了人工手动修图的繁琐步骤,缩短了同类型图像进行修图的时间,在日常的照片处理方面有重要意义,用数字图像处理的技术解决了生活实际问题。


2 基本原理描述

(1)首先选择一张将要处理的图像,将其从 unit 类型转化为 double 类型,再将其转换为灰度图像。

(2)在灰度图像的背景上选择一个或多个生长点,然后用区域生长法将目标和背景进行分割。应用区域生长算法时,要根据不同的图像特征合理地选取其生长点、生长半径和生长阈值。如果有树枝类遮挡物,那生长半径需要选大一点。如果前景和后景灰度值相差较小,则需使用较大的生长阈值。

(3)得到一个二值图像之后,再用形态学处理填充未分隔成功的孔洞,得到最终的二值图像。

(4)根据此二值图像构造出前景底片和后景底片,分别用于目标和新背景的贴印。另外通过边缘检测算法画出边缘图。

(5)将目标和新背景分别与前景底片和后景底片相乘得到两个“底图”,然后将这两张“底图”相加即可得到拼接后的图像。

(6)然后将新背景的 RGB 转换为 HSV,获取其亮度,再将其亮度融合到目标所在的“底图”,即实现对两张图像的融合。

(7)最后根据第三步得到边缘图的边缘线,来对图像进行边缘处理和图像修复,从而得到最终的融合图像。

基本原理流程图:


3 实验数据来源

3.1 原始图像的来源

● 本次课程考核大作业一共选取了三幅图像作为原始待处理的图像,图像类型为 RGB,前两幅图像来源于网络,最后一张是用手机拍摄后再用电脑调整分辨率后得到的。其中,“总统府”的分辨率为 960×720 像素,“长江边”的分辨率为 960×720 像素,“操场”的分辨率为 960×720 像素。三幅原始待处理的图像如图 3.1、图 3.2、图 3.3 所示。

图3.1 总统府:

图3.2 长江边:

图3.3 操场:

3.2 天空背景图像的来源

● 本次课程考核大作业一共选取了三幅天空背景图像对原始图像进行转,图像类型为 RGB,两幅图像分别为“晴天”“黄昏”“星空”,图像均来源于网络,其中“晴天”背景图像的分辨率为:960×720 像素,“黄昏”背景图像的分辨率为: 960×720 像素,“星空”背景图像的分辨率为 960×720 像素。三幅天空背景图像如图 3.4、图 3.5、图 3.6 所示。

图3.4 晴天:

图3.5 黄昏:

图3.6 星空:


4 实验步骤及相应处理结果

4.1 原始图像的预处理

● 由于后续的运算中数据类型都是 double 型,所以需要先对图像矩阵中数据的数据类型进行转换,将 unit 数据类型转换为 double 型。用 imread 函数读入原始图像,将 unit 数据类型转换为 double 型,然后用 imshow 函数显示原图像。相关程序代码如下。

%---------------原始图像读取(start)---------------
originalImageRGB = imread(originalImageFilename); % 读入原始图像
originalImageRGB = im2double(originalImageRGB); % 将 unit 类型转换为 double 类型
if draw_flag == 0figure(1),imshow(originalImageRGB),title('原始图像');
elsesubplot(3,4,1),imshow(originalImageRGB),title('原始图像');
end
%---------------原始图像读取(end)---------------

● 读入后显示的图像如图 4.1 所示:

● 后续操作需要用区域生长法对图像进行分割,而 RGB 图像数据量大,进行区域生长复杂,为了提高程序运行的效率,减少程序的运算量,可以直接对灰度图像进行区域生长,所以将原始的 RGB 图像转换为灰度图像。使用 rgb2gray 函数将原始的 RGB 图像转换为灰度图像,灰度图像的数据类型转换为 double 型,最后用 imshow 函数显示灰度图像。相关程序代码如下。

%---------------原始RGB图像 → 灰度图像(start)---------------
grayImage = rgb2gray(originalImageRGB);
% imshow(grayImage),title('灰色图')
% imshow(originalImageRGB(:,:,1)),title('红色通道');
% imshow(originalImageRGB(:,:,2)),title('绿色通道');
% imshow(originalImageRGB(:,:,3)),title('蓝色通道');
if draw_flag == 0figure(2),imshow(grayImage),title('灰度图像');
else subplot(3,4,2),imshow(grayImage),title('灰度图像');
end
%---------------原始RGB图像 → 灰度图像(end)-----------------

图像类型转换后显示的图像如图 4.2 所示:

4.2 区域生长法分割图像

● 完成图像的背景转换需要把原始图像的背景与目标预留部分进行分离,在比较多种分割方法后,选择采用区域生长法来分割图像背景。区域生长法主要考虑像素及其空间邻域像素之间的关系,开始时确定一个或多个像素点作为种子,然后按某种相似性准则增长区域,将相邻的具有相似性质的像素或区域归并,从而逐步增长区域,直到没有可以归并的点或其他小区域为止。区域内像素的相似性度量可以是平均灰度值、纹理、颜色等信息,本次选择灰度值为区域内像素的相似性度量进行区域生长。

● 首先用 size 函数获取灰度图像的尺寸,然后用 getpts 函数(需要鼠标自行点击选取)选择种子点,用 round 将种子点的坐标取整,存放种子点的灰度值,根据原灰度图像的尺寸大小构造相同大小的全零矩阵以提高运算的效率,设置存储符合区域生长条件的点数初值为在屏幕中选取的种子点数 seeds_num,然后设置一个阈值 threshold,再根据嵌套的 for 循环和 if条件语句判断目标点以及其八零域的点是否满足生长规则,最后即可得到区域生长的二值图像结果,用 imshow 将其显示出来。

● 种子点和阈值的选择并不是固定不变的,在区域生长分割图像的过程中,可以根据区域生长的结果不断地对种子点和阈值 threshold 进行调整。同时对于生长半径r,也要根据图像的特张来选取。如果有“树枝类”遮挡物分割了背景,那么生长半径r应该适度地调大,直到出现满意的结果为止。相关程序代码如下。

图4.3 区域生长原理图:

%---------------区域生长算法(start)-----------------------
[seed_y,seed_x] = getpts; % 选取种子点(可以选取多个)
seed_x = round(seed_x); % 横纵坐标取整
seed_y = round(seed_y); seeds_num = length(seed_x); % 种子个数
seeds = [seed_x,seed_y]; % 各个种子的坐标[Height,Width] = size(grayImage); % 获取图像的大小
Mark_1 = zeros(Height,Width); % 初始化标记矩阵(一开始均未标记)
total_gray = 0;
for i=1:seeds_numtotal_gray = total_gray + grayImage(seed_x(i),seed_y(i));Mark_1(seed_x(i),seed_y(i)) = 1; % 将种子所在区域的点设为"已标记"
end
seed_mean_gray = total_gray ./ seeds_num; % 种子区域的灰度平均值r = grow_radius; % 扫描半径(生长半径)
flag = true; % 生长条件的标志(结束时变为 flase)
i_sta = 1;
i_end = seeds_num;
threshold = grow_threshold;
seeds = [seeds;zeros(2000000,2)]; % 预分配, 提升运算时间
while flagflag = false;for i = i_sta:i_endx = seeds(i,1);y = seeds(i,2);for u = -r:r % 判断周围 r^2-1 个点是否符合生长规则for v = -r:rif x+u>0 && x+u<Height && y+v>0 && y+v<Widthif Mark_1(x+u,y+v)==0 && abs(grayImage(x+u,y+v)-seed_mean_gray)<=thresholdMark_1(x+u,y+v) = 1;flag = true;seeds_num = seeds_num + 1;seeds(seeds_num,1) = x+u;seeds(seeds_num,2) = y+v;seed_mean_gray = (seed_mean_gray .* (seeds_num-1) + ...grayImage(x+u,y+v)) ./ seeds_num;endendendend
end
i_sta = i_end+1;
i_end = seeds_num;
end
if draw_flag == 0figure(3),imshow(Mark_1),title('区域生长分割后的二值图像');
else subplot(3,4,3),imshow(Mark_1),title('区域生长分割后的二值图像');
end
%---------------区域生长算法(end)-----------------------

图4.4 区域生长分割后的二值图像:

4.3 形态学处理填充孔洞

● 在上一个步骤用区域生长法进行图像分割时,由于人为对种子点和阈值进行选择,得到的结果难免出现背景所对应的二值图像部分中存在空洞的现象,这种空洞对后期结果的影响是非常大的,所以需要用形态学处理对背景所对应的二值图像部分中的孔洞进行填充。形态学处理填充空洞选择imfill函数对得到的二值图像进行处理,然后显示填充孔洞之后的二值图像。相关代码如下。

%---------------孔洞填充(start)-----------------------
Mark_1=imfill(Mark_1,'holes');
if draw_flag == 0figure(4),imshow(Mark_1),title('填充孔洞后的二值图像');
else subplot(3,4,4),imshow(Mark_1),title('填充孔洞后的二值图像');
end
%---------------孔洞填充(end)-------------------------

图4.5 填充孔洞后的二值图像:

4.4 边缘检测+根据二值图像构造RGB图像

● 原图像与背景图像均为 RGB 图像,进行区域生长和形态学处理填充孔洞之后得到的图像是一个二值图像,所以要根据此二值图像构造边缘图像和两个 RGB 图像(前景和后景)。之后会与后续步骤中与原图像、背景相乘以得到“底图”。
● 边缘检测原理图:遍历二值图像矩阵,对每一个点进行扫描,如果它周围存在一个与它值相反的像素点,就把它周围 8 个点都标记为边缘点。

图4.6 边缘检测原理图:

前后景提取原理: 先构造两个与原图像大小相同的全零矩阵,然后用嵌套的 for 循环对图像进行遍历,当一点像素值为 1 时,给第一个全零矩阵中这个位置的像素的 RGB 颜色分量全部赋值 1,给第二个全零矩阵中这个位置的像素的 RGB 颜色分量全部赋值 0;当一点像素值为 0 时,给第一个全零矩阵中这个位置的像素的 RGB 颜色分量全部赋值 0,给第二个全零矩阵中这个位置的像素的 RGB 颜色分量全部赋值 1,完成全部像素的遍历和赋值后,显示这两个 RGB 图像。这样就根据二值图像构造了两个 RGB 图像。相关程序代码如下。

%---------------边缘检测+原图前后景抠取(start)-----------------------
Edge = zeros(Height,Width);
edge_points = zeros(200000,2); % 预分配, 以提升运算时间
edge_points_sum = 0;
Mark_2 = zeros(Height,Width); % 准备放原图的前景
Mark_3 = zeros(Height,Width); % 准备放背景的后景
for i = 1:Heightfor j = 1:Widthif Mark_1(i,j) == 0for u = -1:1for v = -1:1if i+u>0 && i+u<Height && j+v>0 && j+v<Widthif Mark_1(i,j) == 0 && Mark_1(i+u, j+v) == 1 % 把边缘找出来(1代表白色)edge_points_sum = edge_points_sum + 1;edge_points(edge_points_sum, 1) = i;edge_points(edge_points_sum, 2) = j;edge_points(edge_points_sum, 1) = i+u;edge_points(edge_points_sum, 2) = j+v;Edge(i,j) = 1; Edge(i+u, j+v) = 1;elseif Mark_1(i,j) == 1 && Mark_1(i+u, j+v) == 0Edge(i,j) = 0;Edge(i+u, j+v) = 0; endendendendendif Mark_1(i,j) == 0Mark_2(i,j,1) = 1; % 白色是1Mark_2(i,j,2) = 1; % 白色是1Mark_2(i,j,3) = 1; % 白色是1Mark_3(i,j,1) = 0; % 黑色是0Mark_3(i,j,2) = 0; % 黑色是0Mark_3(i,j,3) = 0; % 黑色是0elseMark_2(i,j,1) = 0; Mark_2(i,j,2) = 0; Mark_2(i,j,3) = 0; Mark_3(i,j,1) = 1; Mark_3(i,j,2) = 1; Mark_3(i,j,3) = 1; endend
end
if draw_flag == 0figure(5),imshow(Edge),title('边缘检测图');
elsesubplot(3,4,5),imshow(Edge),title('边缘检测图');
endif draw_flag == 0figure(6),imshow(Mark_2),title('准备放原图的前景底片(白色部分)');
elsesubplot(3,4,6),imshow(Mark_2),title('准备放原图的前景底片(白色部分)');
end
if draw_flag == 0figure(7),imshow(Mark_3),title('准备放背景的后景底片(白色部分)');
elsesubplot(3,4,7),imshow(Mark_3),title('准备放背景的后景底片(白色部分)');
end
originalImageRGB_1 = originalImageRGB .* Mark_2;
if draw_flag == 0figure(8),imshow(originalImageRGB_1),title('去除背景后并在前后景底片区域的图像');
elsesubplot(3,4,8),imshow(originalImageRGB_1),title('去除背景后并在前后景底片区域的图像');
end
%---------------边缘检测+原图前后景底片抠取(end)-----------------------

图4.7 综合图片组:



● 对于新背景,我们做同样的处理,这里需要剪裁一下,使得新背景的大小和原图的一样。用剪裁后的新背景和后景底片相乘即得新的背景图像。

%---------------后景底片剪裁+抠取(start)-----------------------
backgroungImage = imread(backgroungImageFilename);
backgroungImage = im2double(backgroungImage);backgroungImage = backgroungImage(1:Height,1:Width,:); % 按比例剪裁图片
backgroungImage_1 = backgroungImage .* Mark_3;
if draw_flag == 0figure(9),imshow(backgroungImage_1),title('在底片区域的背景图像');
elsesubplot(3,4,9),imshow(backgroungImage_1),title('在底片区域的背景图像');
end
%---------------后景底片剪裁+抠取(end)-------------------------

图4.8 在后景底片区域的背景图像:

4.5 图像拼接

● 由于去除后景后的图像中,背景部分的 [R,G,B]=[0,0,0] ,而在去除前景后的图像中,背景区域的 [R,G,B]=[0,0,0],所以将二者直接相加,即可将两张图片进行合成,得到拼接后的图像。相关程序代码如下。

%---------------图片拼接(start)---------------------
jointImage = originalImageRGB_1 + backgroungImage_1;
if draw_flag == 0figure(10),imshow(jointImage),title('拼接后的图像');
elsesubplot(3,4,10),imshow(jointImage),title('拼接后的图像');
end
%---------------图片拼接(end)-----------------------

图4.9 拼接后的图像:

4.6 图像整体融合

● 在对新获得的图像进行进一步处理的时候,先通过颜色空间转换将 RGB 转化为 HSV,然后选择提取原图片或者新背景图片的平均亮度作为主亮度值,并依据获得的主亮度值将拼接后得到的图像中所有像素的亮度重新赋值,再通过颜色空间转换重新变为 RGB,得到整体融合后的图像。相关程序代码如下。

图4.10 亮度融合原理图:

%---------------图像整体融合(start)---------------------
originalImageRGB_HSV = rgb2hsv(originalImageRGB); % 颜色空间转换: RGB → HSV
o_s = originalImageRGB_HSV(:,:,2); % 饱和度
o_v = originalImageRGB_HSV(:,:,3); % 亮度
[n,m] = size(o_s);
mean_o_s = sum(sum(o_s)) ./ (n * m);
[n,m] = size(o_v);
mean_o_v = sum(sum(o_v)) ./ (n * m);
backgroungImageRGB_HSV = rgb2hsv(backgroungImage);
b_s = backgroungImageRGB_HSV(:,:,2); % 饱和度
b_v = backgroungImageRGB_HSV(:,:,3); % 亮度
[n,m] = size(b_s);
mean_b_s = sum(sum(b_s)) ./ (n * m);
[n,m] = size(b_v);
mean_b_v = sum(sum(b_v)) ./ (n * m);
jointImage_HSV = rgb2hsv(jointImage);
choose = input('主亮度选择,请输入0或1,0代表原图片,1代表背景图片:');
if choose == 0for i = 1:Heightfor j = 1:Widthif Mark_2(i,j) == 0tmp1 = jointImage_HSV(i,j,3) .* mean_o_v ./ mean_b_v;if 0.95 < tmp1jointImage_HSV(i,j,3) = tmp1 .* 0.95;elsejointImage_HSV(i,j,3) = tmp1;endendendend
elsefor i = 1:Heightfor j = 1:Widthif Mark_2(i,j) == 1tmp1 = jointImage_HSV(i,j,3) ./ mean_o_v .* mean_b_v;if 0.95 < tmp1jointImage_HSV(i,j,3) = tmp1 .* 0.95;elsejointImage_HSV(i,j,3) = tmp1;endendendend
end
jointImage = hsv2rgb(jointImage_HSV); % HSV → RGB 得到最终图片
if draw_flag == 0figure(11),imshow(jointImage),title('图像整体融合后的图像');
elsesubplot(3,4,11),imshow(jointImage),title('图像整体融合后的图像');
end
%---------------图像整体融合(end)---------------------

图4.11 整体融合后的图像:

4.7 边缘处理

● 最后对融合后的图像做细节处理,将每一个边缘点周围 8 个点的像素值(3 个通道)取平均值,作为该边缘点新的像素值。

图4.12 边缘处理原理图:

%---------------边缘处理(stert)---------------------
mix_r = mix_radius; % 融合边缘的半径选取
for i = 1:edge_points_sumx = edge_points(i,1);y = edge_points(i,2);R = 0;G = 0;B = 0;for u = -mix_r:mix_rfor v = -mix_r:mix_rif x+u>0 && x+u<Height && y+v>0 && y+v<WidthR = R + jointImage(x+u,y+v,1);G = G + jointImage(x+u,y+v,2);B = B + jointImage(x+u,y+v,3);endendjointImage(x,y,1) = R ./ (4*mix_r^2 + 4*mix_r^2);jointImage(x,y,2) = G ./ (4*mix_r^2 + 4*mix_r^2);jointImage(x,y,3) = B ./ (4*mix_r^2 + 4*mix_r^2);end
end
if draw_flag == 0figure(12),imshow(jointImage),title('边缘融合后的图像');
elsesubplot(3,4,12),imshow(jointImage),title('边缘融合后的图像');
end
%---------------边缘处理(end)-----------------------

图4.13 边缘处理后的图像:

图4.14 细节处理对比图(右边为已处理图):


5 实验结果分析

● 在对图像进行预处理时,将 unit 数据类型转换成了 double 型,有利于后续对图像的运算处理,再将原 RGB 图像转换成灰度图像并成功地显示了出来。

● 在使用区域生长法分割图像时,种子点和阈值的选择并不是固定不变的,在区域生长分割图像的过程中,可以根据区域生长的结果不断地对种子点和阈值进行调整,直到出现我们满意的结果为止,再将处理此图像的种子点和阈值设置为定值。有的时候二值图像中背景对应的部分会存在孔洞,是由于种子点和阈值的选择不恰当所引起的,但因为后续会对图像进行形态学处理,所以对于最后的实验结果影响并不大。

● 在对图像的形态学处理中,imfill 函数可以很好地对二值图像中背景对应的部分地孔洞进行填充,有效地解决了区域生长分割图像时产生的孔洞。

● 通过边缘检测,可以找出需要更换的背景部分的边缘。

● 在根据二值图像构造 RGB 图像时,成功地得到了基于二值图像的一对 RGB 图像,分别是准备放原图的前景底片(白色部分)和准备放背景的后景底片(白色部分),将准备放原图的前景底片(白色部分)与原 RGB 图像相点乘后,得到了去除背景后并在前景底片区域的图像。将 RGB 背景图像放进程序处理,使得 RGB 背景图像的尺寸与原图像尺寸相同。再将准备放背景的后景底片(白色部分)与背景图像相点乘后,得到了在后景底片区域的背景图像。然后将去除背景后并在前景底片区域的图像与后景底片区域的背景图像相加,成功地得到了拼接后的图像。

● 在图像的整体融合时,先通过颜色空间转换化为 HSV,再选择背景图片的亮度作为主亮度,改变拼接后的图像的亮度,使得原图亮度与背景亮度相近,然后通过颜色空间转换重新转换为 RGB,得到图像整体融合后的图像。

● 最后,通过边缘处理,使得拼接后图像拼接部分更加自然,得到最终图像。各部分程序均起到了作用,成功地实现了图像背景的转换与亮度融合。

6 总结与心得体会

● 通过这段时间的课程学习,深入了解了许多数字图像的相关知识,虽不能完全掌握图像处理技术,但在此次课程大作业中,我们把所学的知识付诸实践,选择做了一种基于区域生长和形态学处理转换图片背景的方法。它能够将照片中的背景替换为其他想要的背景,操作十分简单,处理速度快,可以成功地对照片进行背景转换,并通过边缘融合等技术,使得转换后的图片看起来更加和谐,减轻违和感。这种技术大大缩短了同类型修图的时间,可以广泛应用于日常照片的处理,对于现实生活问题具有实际意义。

● 在进行课程作业实验的过程中,我们选择通过区域生长法对原图像转换而来的灰度图像进行分割,得到了区分背景与目标的二值图像,并依据此二值图像构造一对 RGB 图像,通过这对 RGB 图像分别提取背景与预留的目标图像部分,再拼接完成图像的区域转换;而后在进一步处理获得的新图像的时候,提取想要替换的背景的信息,将所有像素的亮度重新赋值,并进行边缘融合,以使得新背景与预留图像相融合,实现更好的视觉效果。

● 但是在编写代码的过程中,我们也遇到了很多问题,例如对彩色图像处理还不是很熟练,对图像的形态学处理也不熟悉,但是可以快速去回顾理论课上所学的知识,然后对这些知识进一步地进行验证,并通过网络查找有关资料加以学习,以运用到实践中实现想要的特定功能。我们研究出的这个方法仍存在一些不足,还有许多地方可以进一步地优化,以达到更好的使用效果。比如说,对于生长阈值和生长半径需要人为地调整,这需要一定的调试经验后才能调出理想的结果。通过本次课程大作业的合作,我们每个人都受益匪浅。


7 完整代码

Matlab2020:

% 软件:MATLAB2020
clc;
clear;
close all;%--------------初始值设定(start)-----------------
originalImageFilename = './test_img/river.jpg'; % 原图片(自己设定)
backgroungImageFilename = './test_img/Xing_stars.png'; % 背景图片(自己设定)
draw_flag = 0; % 画图选择(0或者1)
grow_radius = 3; % 生长半径
grow_threshold = 0.13; % 生长阈值
mix_radius = 1 ; % 融合边缘的半径
%--------------初始值设定(end)-------------------%---------------原始图像读取(start)---------------
originalImageRGB = imread(originalImageFilename); % 读入原始图像
originalImageRGB = im2double(originalImageRGB); % 将 unit 类型转换为 double 类型
if draw_flag == 0figure(1),imshow(originalImageRGB),title('原始图像');
elsesubplot(3,4,1),imshow(originalImageRGB),title('原始图像');
end
%---------------原始图像读取(end)---------------%---------------原始RGB图像 → 灰度图像(start)---------------
grayImage = rgb2gray(originalImageRGB);
% imshow(grayImage),title('灰色图')
% imshow(originalImageRGB(:,:,1)),title('红色通道');
% imshow(originalImageRGB(:,:,2)),title('绿色通道');
% imshow(originalImageRGB(:,:,3)),title('蓝色通道');
if draw_flag == 0figure(2),imshow(grayImage),title('灰度图像');
else subplot(3,4,2),imshow(grayImage),title('灰度图像');
end
%---------------原始RGB图像 → 灰度图像(end)-----------------%---------------区域生长算法(start)-----------------------
[seed_y,seed_x] = getpts; % 选取种子点(可以选取多个)
seed_x = round(seed_x); % 横纵坐标取整
seed_y = round(seed_y); seeds_num = length(seed_x); % 种子个数
seeds = [seed_x,seed_y]; % 各个种子的坐标[Height,Width] = size(grayImage); % 获取图像的大小
Mark_1 = zeros(Height,Width); % 初始化标记矩阵(一开始均未标记)total_gray = 0;
for i=1:seeds_numtotal_gray = total_gray + grayImage(seed_x(i),seed_y(i));Mark_1(seed_x(i),seed_y(i)) = 1; % 将种子所在区域的点设为"已标记"
end
seed_mean_gray = total_gray ./ seeds_num; % 种子区域的灰度平均值r = grow_radius; % 扫描半径(生长半径)
flag = true; % 生长条件的标志(结束时变为 flase)
i_sta = 1;
i_end = seeds_num;
threshold = grow_threshold;
seeds = [seeds;zeros(2000000,2)]; % 预分配, 提升运算时间
while flagflag = false;for i = i_sta:i_endx = seeds(i,1);y = seeds(i,2);for u = -r:r % 判断周围 r^2-1 个点是否符合生长规则for v = -r:rif x+u>0 && x+u<=Height && y+v>0 && y+v<=Widthif Mark_1(x+u,y+v)==0 && abs(grayImage(x+u,y+v)-seed_mean_gray)<=thresholdMark_1(x+u,y+v) = 1;flag = true;seeds_num = seeds_num + 1;seeds(seeds_num,1) = x+u;seeds(seeds_num,2) = y+v;seed_mean_gray = (seed_mean_gray .* (seeds_num-1) + ...grayImage(x+u,y+v)) ./ seeds_num;endendendendendi_sta = i_end+1;i_end = seeds_num;
end
if draw_flag == 0figure(3),imshow(Mark_1),title('区域生长分割后的二值图像');
else subplot(3,4,3),imshow(Mark_1),title('区域生长分割后的二值图像');
end
%---------------区域生长算法(end)-----------------------%---------------孔洞填充(start)-----------------------
Mark_1=imfill(Mark_1,'holes');
if draw_flag == 0figure(4),imshow(Mark_1),title('填充孔洞后的二值图像');
else subplot(3,4,4),imshow(Mark_1),title('填充孔洞后的二值图像');
end
%---------------孔洞填充(end)-------------------------%---------------边缘检测+原图底片抠取(start)-----------------------
Edge = zeros(Height,Width);
edge_points = zeros(200000,2); % 预分配, 以提升运算时间
edge_points_sum = 0;
Mark_2 = zeros(Height,Width); % 准备放原图的底片
Mark_3 = zeros(Height,Width); % 准备放背景的底片
for i = 1:Heightfor j = 1:Widthif Mark_1(i,j) == 0for u = -1:1for v = -1:1if i+u>0 && i+u<=Height && j+v>0 && j+v<=Widthif Mark_1(i,j) == 0 && Mark_1(i+u, j+v) == 1 % 把边缘找出来(1代表白色)if Edge(i,j) == 0edge_points_sum = edge_points_sum + 1;edge_points(edge_points_sum, 1) = i;edge_points(edge_points_sum, 2) = j;endedge_points_sum = edge_points_sum + 1;edge_points(edge_points_sum, 1) = i+u;edge_points(edge_points_sum, 2) = j+v;Edge(i,j) = 1; Edge(i+u, j+v) = 1;elseif Mark_1(i,j) == 1 && Mark_1(i+u, j+v) == 0 if Edge(i,j) == 0edge_points_sum = edge_points_sum + 1;edge_points(edge_points_sum, 1) = i;edge_points(edge_points_sum, 2) = j;endedge_points_sum = edge_points_sum + 1;edge_points(edge_points_sum, 1) = i+u;edge_points(edge_points_sum, 2) = j+v;Edge(i,j) = 1;Edge(i+u, j+v) = 1;endendendendendif Mark_1(i,j) == 0Mark_2(i,j,1) = 1; % 白色是1Mark_2(i,j,2) = 1; % 白色是1Mark_2(i,j,3) = 1; % 白色是1Mark_3(i,j,1) = 0; % 黑色是0Mark_3(i,j,2) = 0; % 黑色是0Mark_3(i,j,3) = 0; % 黑色是0elseMark_2(i,j,1) = 0; Mark_2(i,j,2) = 0; Mark_2(i,j,3) = 0; Mark_3(i,j,1) = 1; Mark_3(i,j,2) = 1; Mark_3(i,j,3) = 1; endend
end
if draw_flag == 0figure(5),imshow(Edge),title('边缘检测图');
elsesubplot(3,4,5),imshow(Edge),title('边缘检测图');
endif draw_flag == 0figure(6),imshow(Mark_2),title('准备放原图的底片(白色部分)');
elsesubplot(3,4,6),imshow(Mark_2),title('准备放原图的底片(白色部分)');
endif draw_flag == 0figure(7),imshow(Mark_3),title('准备放背景的底片(白色部分)');
elsesubplot(3,4,7),imshow(Mark_3),title('准备放背景的底片(白色部分)');
endoriginalImageRGB_1 = originalImageRGB .* Mark_2;
if draw_flag == 0figure(8),imshow(originalImageRGB_1),title('去除背景后并在底片区域的图像');
elsesubplot(3,4,8),imshow(originalImageRGB_1),title('去除背景后并在底片区域的图像');
end
%---------------边缘检测+原图底片抠取(end)-----------------------%---------------背景底片剪裁+抠取(start)-----------------------
backgroungImage = imread(backgroungImageFilename);
backgroungImage = im2double(backgroungImage);backgroungImage = backgroungImage(1:Height,1:Width,:); % 按比例剪裁图片
backgroungImage_1 = backgroungImage .* Mark_3;
if draw_flag == 0figure(9),imshow(backgroungImage_1),title('在底片区域的背景图像');
elsesubplot(3,4,9),imshow(backgroungImage_1),title('在底片区域的背景图像');
end
%---------------背景底片剪裁+抠取(end)-------------------------%---------------图片拼接(start)---------------------
jointImage = originalImageRGB_1 + backgroungImage_1;
if draw_flag == 0figure(10),imshow(jointImage),title('拼接后的图像');
elsesubplot(3,4,10),imshow(jointImage),title('拼接后的图像');
end
%---------------图片拼接(end)-----------------------%---------------图像整体融合(start)---------------------
originalImageRGB_HSV = rgb2hsv(originalImageRGB); % 颜色空间转换: RGB → HSV
o_s = originalImageRGB_HSV(:,:,2); % 饱和度
o_v = originalImageRGB_HSV(:,:,3); % 亮度
[n,m] = size(o_s);
mean_o_s = sum(sum(o_s)) ./ (n * m);
[n,m] = size(o_v);
mean_o_v = sum(sum(o_v)) ./ (n * m);backgroungImageRGB_HSV = rgb2hsv(backgroungImage);
b_s = backgroungImageRGB_HSV(:,:,2); % 饱和度
b_v = backgroungImageRGB_HSV(:,:,3); % 亮度
[n,m] = size(b_s);
mean_b_s = sum(sum(b_s)) ./ (n * m);
[n,m] = size(b_v);
mean_b_v = sum(sum(b_v)) ./ (n * m);jointImage_HSV = rgb2hsv(jointImage); choose = input('主亮度选择,请输入0或1,0代表原图片,1代表背景图片:');
if choose == 0for i = 1:Heightfor j = 1:Widthif Mark_2(i,j) == 0% jointImage_HSV(i,j,2) = jointImage_HSV(i,j,2) .* mean_o_s ./ mean_b_s;tmp1 = jointImage_HSV(i,j,3) .* mean_o_v ./ mean_b_v;if 0.95 < tmp1jointImage_HSV(i,j,3) = tmp1 .* 0.95;elsejointImage_HSV(i,j,3) = tmp1;endendendend
elsefor i = 1:Heightfor j = 1:Widthif Mark_2(i,j) == 1tmp1 = jointImage_HSV(i,j,3) ./ mean_o_v .* mean_b_v;if 0.95 < tmp1jointImage_HSV(i,j,3) = tmp1 .* 0.95;elsejointImage_HSV(i,j,3) = tmp1;endendendend
end
jointImage = hsv2rgb(jointImage_HSV); % HSV → RGB 得到最终图片
if draw_flag == 0figure(11),imshow(jointImage),title('图像整体融合后的图像');
elsesubplot(3,4,11),imshow(jointImage),title('图像整体融合后的图像');
end
%---------------图像整体融合(end)---------------------%---------------边缘处理(stert)---------------------
mix_r = mix_radius; % 融合边缘的半径选取
for i = 1:edge_points_sumx = edge_points(i,1);y = edge_points(i,2);R = 0;G = 0;B = 0;for u = -mix_r:mix_rfor v = -mix_r:mix_rif x+u>0 && x+u<=Height && y+v>0 && y+v<=WidthR = R + jointImage(x+u,y+v,1);G = G + jointImage(x+u,y+v,2);B = B + jointImage(x+u,y+v,3);endendjointImage(x,y,1) = R ./ (4*mix_r^2 + 4*mix_r^2);jointImage(x,y,2) = G ./ (4*mix_r^2 + 4*mix_r^2);jointImage(x,y,3) = B ./ (4*mix_r^2 + 4*mix_r^2);end
end
if draw_flag == 0figure(12),imshow(jointImage),title('边缘处理后的图像');
elsesubplot(3,4,12),imshow(jointImage),title('边缘处理后的图像');
end
%---------------边缘处理(end)-----------------------

8 补充说明及下载链接

● 完整文档、所有测试图片、代码使用说明的链接:https://download.csdn.net/download/Wang_Dou_Dou_/87535824

● 若有写得不对的地方,或有疑问,欢迎评论交流。


⭐️ ⭐️

基于区域生长和形态学处理的图像融合方法——Matlab图像处理相关推荐

  1. 【图像融合】基于DCT域实现多焦点图像融合含Matlab源码

    1 内容介绍 在诸如无线视觉传感器网络(wireless visual sensor networks, WVSN)中,多个空间位置相邻的传感摄像头监测同一场景时将获得多幅图像或多个视频序列,但这些图 ...

  2. matlab气管分割,一种基于区域生长法与水平集相融合的肺部CT图像的分割

    摘要: 为将肺实质区域从含有背景.噪声的胸腔区域里分割出来,首先,应用传统的区域生长法初步定位肺部边界轮廓:其次,去除肺部边界噪声,采用自适应曲率阈值法修复肺部边界:最后,应用水平集法中的DRLSE模 ...

  3. 【毕业设计/matlab系列】基于区域生长和形态学处理的道路检测实现【含Matlab源码】

    Date:2022.6.11 文章目录 代码获取方式 1.前言 2.实现效果 3.部分matlab代码 代码获取方式 方式一:订阅付费专栏 <毕业设计代码进阶版>,可获取该付费专栏中任意代 ...

  4. 帮推|基于深度学习的图像融合方法综述

    基于深度学习的图像融合方法综述 博主朋友关于图像融合的综述论文基于深度学习的图像融合方法综述已被<中国图象图形学报>正式接收! 极力推荐想要入门图像融合领域的小伙伴下载学习,此外希望在图像 ...

  5. 基于深度学习的多聚焦图像融合(Multi-Focus Image Fusion)论文及代码整理

    基于深度学习的多聚焦图像融合(Multi-Focus Image Fusion)论文及代码整理 首先附上近期整理基于深度学习的图像融合论文的思维导图 本篇博客主要整理基于深度学习的多曝光图像融合的论文 ...

  6. 基于深度学习的多曝光图像融合(Multi-exposure Image Fusion)论文及代码整理

    基于深度学习的多曝光图像融合(Multi-exposure Image Fusion)论文及代码整理 首先附上近期整理基于深度学习的图像融合论文的思维导图 本篇博客主要整理基于深度学习的多曝光图像融合 ...

  7. 金字塔图像融合方法总结(一)

    一.高斯金字塔和下采样 为了获取层级为 G_i+1 的金字塔图像,我们采用如下方法: <1>对图像G_i进行高斯内核卷积 <2>将所有偶数行和列去除 得到的图像即为G_i+1的 ...

  8. IHS图像融合方法+Python代码

    IHS图像融合方法+Python代码 1.方法原理 HIS为:亮度(I ).色调(H).饱和度(S): 强度表示光谱的整体亮度大小,对应于图像的空间分辨率: 传统的IHS图像融合方法基本思想是将IHS ...

  9. 几种常规的图像融合方法及其原理

    目前,根据图像融合的层次,将图像融合算法分为像素级图像融合,特征级图像融合和决策级图像融合.像素级图像融合处理主要是在图像像素层面上操作处理图像数据,属于基础层次的图像融合.优点是可以保持源图像更多的 ...

最新文章

  1. 查看mysql.sock_如何查找 mysql 的mysql.sock文件?
  2. flutter - dart基础之map
  3. wcf简单的创建和运用
  4. Apache AB 压力测试
  5. C语言选择结构和循环结构的汇总
  6. kuangbin专题一 简单搜索
  7. linux程序中expr是什么意思,Linux中expr命令 (转)
  8. 3分钟了解计算机基础知识,你对电脑还一无所知?3分钟带你全面了解电脑基础知识...
  9. MapGIS 6.7 数字非标准分幅影像校正方法
  10. matlab关于图像切割的一些总结:imcrop,getrect,ndgrid,函数
  11. python断言使用方法
  12. tex 表格内容换行_LaTex表格内单元格内容强制换行
  13. Cesium模型压平
  14. 【通信原理】揭开傅里叶级数与傅里叶变换的神秘面纱
  15. Android Banner图片轮播第三方框架
  16. App列表之下拉刷新
  17. 如何让网页显示友好的错误信息页面
  18. 网站加入QQ在线即时交谈的代码
  19. qq群淘客怎么引流?淘客新手如何利用qq群引流?
  20. 自从我用了这些浏览器插件,工作效率至少提高了一倍,谷歌浏览器插件

热门文章

  1. 面试 | 测试开发岗位面试题目回顾
  2. 硬核榜单 | 拍乐云荣登福布斯中国「企业科技50强」
  3. Oracle11g数据库创建表的方式——Sqlplus命令和企业管理器
  4. 动态路由渲染(思路)
  5. 姿态角是怎么测量出来的
  6. VS2008C#Sqlserver2008数据库的连接,增删改查
  7. discuz 上传头像时 提示 目录不可写 Can not write to the data/tmp folder!
  8. 创建和删除win7/vista下的启动引导项 - BCD编辑器简介
  9. Web安全试验:修改HTTP请求
  10. 关于电脑开(WIFI、蓝牙)热点其他设备无法连接的问题