当前位置: 首页 > news >正文

Criminisi图像修复MATLAB实现

Criminisi图像修复MATLAB实现,这是目前**纹理/结构型破损(划痕、物体移除、大面积缺损)**的经典算法,比传统的TV/Inpainting模型更擅长保持纹理连续性,也是Adobe Photoshop“内容识别填充”的早期核心算法之一。


一、Criminisi算法核心逻辑

Criminisi是基于纹理合成的优先级修复算法,核心解决“先修哪里、用什么修”两个问题:

  1. 优先级计算:优先修复结构明显(梯度强)周围已知信息可靠的区域,符合人类视觉“先看轮廓、再看纹理”的习惯。
  2. 块匹配:从完好区域找和待修复块最相似的纹理块,复制到破损区域,保证纹理一致性。

核心公式

1. 优先级P(p)=C(p)⋅D(p)P(p) = C(p) \cdot D(p)P(p)=C(p)D(p)
  • C(p)C(p)C(p)置信项,衡量待修复块周围已知像素的可靠性(初始已知区域C=1C=1C=1,破损区域C=0C=0C=0)。
  • D(p)D(p)D(p)数据项,衡量待修复点所在边界的结构强度(梯度在边界法向上的投影,值越大结构越明显)。
2. 置信项更新

每次修复完一个块Ψp^\Psi_{\hat{p}}Ψp^,块内新修复像素的置信度统一设为当前块的置信度C(p^)C(\hat{p})C(p^)


二、MATLAB实现

1. 主函数:criminisi_inpaint.m

function[inpainted_img,mask]=criminisi_inpaint(img,mask,patch_size)% CRIMINISI_INPAINT 基于Criminisi算法的图像修复% img: 输入图像 (灰度图,uint8/ double)% mask: 破损掩码 (0=破损区域,255=完好区域,和img同尺寸)% patch_size: 修复块大小 (奇数,推荐9/11/15)% inpainted_img: 修复后图像% mask: 更新后的掩码%% ========== 参数初始化 ==========ifnargin<3,patch_size=9;endhalf_patch=floor(patch_size/2);max_iter=1000;% 最大迭代次数,防止死循环alpha=1e-6;% 归一化常数,避免除零% 转double便于计算ifisa(img,'uint8'),img=im2double(img);endifisa(mask,'uint8'),mask=im2double(mask);endmask=im2bw(mask,0.5);% 确保mask是二值(0/1)[rows,cols]=size(img);% 置信度矩阵:完好区域=1,破损区域=0C=double(mask);% 破损区域标记:Φ=破损,Ω=完好Phi=~mask;% 逻辑矩阵,破损为trueOmega=mask;% 逻辑矩阵,完好的为true%% ========== 预计算图像梯度 ==========% 用Sobel算子计算梯度(x/y方向)[gx,gy]=imgradientxy(img,'sobel');[~,grad_mag]=imgradient(gx,gy);% 梯度幅值grad_mag_max=max(grad_mag(:));% 梯度幅值最大值,用于归一化%% ========== 主修复循环 ==========fprintf('开始Criminisi修复...\n');iter=0;whileany(Phi(:))&&iter<max_iter iter=iter+1;% ---------- 1. 找破损区域的边界δΦ ----------% 形态学操作:腐蚀完好区域,得到边界eroded_Omega=imerode(Omega,strel('disk',1));boundary=Omega&~eroded_Omega;% 边界点:完好区域的外围[b_y,b_x]=find(boundary);% 边界点的坐标ifisempty(b_y),break;end% 无边界,修复完成% ---------- 2. 计算每个边界点的优先级 ----------P=zeros(length(b_y),1);% 优先级数组fori=1:length(b_y)p_y=b_y(i);p_x=b_x(i);% ---- 2.1 计算置信项C(p) ----% 取以p为中心的块,裁剪边界y_min=max(1,p_y-half_patch);y_max=min(rows,p_y+half_patch);x_min=max(1,p_x-half_patch);x_max=min(cols,p_x+half_patch);% 块内的已知像素的置信度平均值block_C=C(y_min:y_max,x_min:x_max);block_Omega=Omega(y_min:y_max,x_min:x_max);ifsum(block_Omega(:))==0C_p=0;elseC_p=mean(block_C(block_Omega));end% ---- 2.2 计算数据项D(p) ----% 边界法向量n:指向破损区域内部(掩码梯度的反方向)% 用中心差分计算掩码梯度ifp_x==1,nx=mask(p_y,p_x+1)-mask(p_y,p_x);elseifp_x==cols,nx=mask(p_y,p_x)-mask(p_y,p_x-1);elsenx=mask(p_y,p_x+1)-mask(p_y,p_x-1);endifp_y==1,ny=mask(p_y+1,p_x)-mask(p_y,p_x);elseifp_y==rows,ny=mask(p_y,p_x)-mask(p_y-1,p_x);elseny=mask(p_y+1,p_x)-mask(p_y-1,p_x);endn_norm=sqrt(nx^2+ny^2+eps);nx=-nx/n_norm;% 取反,指向破损内部ny=-ny/n_norm;% 图像梯度在法向量上的投影grad_dot_n=abs(gx(p_y,p_x)*nx+gy(p_y,p_x)*ny);D_p=grad_dot_n/(alpha+grad_mag_max);% 归一化% ---- 2.3 总优先级 ----P(i)=C_p*D_p;end% ---------- 3. 选优先级最高的点 ----------[~,idx]=max(P);p_hat_y=b_y(idx);p_hat_x=b_x(idx);% ---------- 4. 取以待修复点为中心的块Ψ_p̂ ----------y_min=max(1,p_hat_y-half_patch);y_max=min(rows,p_hat_y+half_patch);x_min=max(1,p_hat_x-half_patch);x_max=min(cols,p_hat_x+half_patch);patch_phi=Phi(y_min:y_max,x_min:x_max);% 块内的破损区域patch_omega=Omega(y_min:y_max,x_min:x_max);% 块内的完好区域% ---------- 5. 在完好区域搜索最佳匹配块 ----------min_ssd=inf;best_q_y=p_hat_y;best_q_x=p_hat_x;% 遍历所有完好区域的可能块中心[omega_y,omega_x]=find(Omega);fori=1:length(omega_y)q_y=omega_y(i);q_x=omega_x(i);% 块不能超出图像边界q_ymin=max(1,q_y-half_patch);q_ymax=min(rows,q_y+half_patch);q_xmin=max(1,q_x-half_patch);q_xmax=min(cols,q_x+half_patch);% 块尺寸必须和待修复块一致if(q_ymax-q_ymin)~=(y_max-y_min)||...(q_xmax-q_xmin)~=(x_max-x_min)continue;end% 计算SSD(平方差和)src_block=img(q_ymin:q_ymax,q_xmin:q_xmax);dst_block=img(y_min:y_max,x_min:x_max);ssd=sum((src_block(patch_omega)-dst_block(patch_omega)).^2,'all');ifssd<min_ssd min_ssd=ssd;best_q_y=q_y;best_q_x=q_x;best_q_ymin=q_ymin;best_q_ymax=q_ymax;best_q_xmin=q_xmin;best_q_xmax=q_xmax;endend% ---------- 6. 复制匹配块到破损区域 ----------src_block=img(best_q_ymin:best_q_ymax,best_q_xmin:best_q_xmax);% 只复制破损的部分img(y_min:y_max,x_min:x_max)=src_block.*double(patch_phi)+...img(y_min:y_max,x_min:x_max).*double(patch_omega);% ---------- 7. 更新置信度和掩码 ----------C(y_min:y_max,x_min:x_max)=C(y_min:y_max,x_min:x_max).*double(patch_omega)+...P(idx).*double(patch_phi);Phi(y_min:y_max,x_min:x_max)=false;% 修复的区域不再是破损Omega(y_min:y_max,x_min:x_max)=true;% 进度提示ifmod(iter,10)==0fprintf('迭代 %d 次,剩余破损像素: %d\n',iter,sum(Phi(:)));endendfprintf('修复完成,总迭代次数: %d\n',iter);inpainted_img=img;mask=Omega;end

2. 测试脚本:demo_criminisi.m

%% demo_criminisi.m Criminisi算法示例clear;clc;close all;%% ========== 1. 准备输入图像和破损掩码 ==========% 读入测试图像(Lena图,确保路径正确)img=imread('lena.png');ifsize(img,3)==3img_gray=rgb2gray(img);% 转为灰度图,彩色图见下文说明elseimg_gray=img;end% 生成破损掩码:在图像中心创建一个50x50的矩形破损mask=ones(size(img_gray));rect_center=[size(img_gray,2)/2,size(img_gray,1)/2];% [x, y]rect_size=[50,50];% [宽, 高]x1=rect_center(1)-rect_size(1)/2;x2=rect_center(1)+rect_size(1)/2;y1=rect_center(2)-rect_size(2)/2;y2=rect_center(2)+rect_size(2)/2;mask(y1:y2,x1:x2)=0;% 破损区域设为0% 可视化破损图像broken_img=img_gray;broken_img(~mask)=0;% 破损区域显示为黑色%% ========== 2. 运行Criminisi修复 ==========patch_size=9;% 修复块大小,奇数,推荐9/11/15[inpainted_img,~]=criminisi_inpaint(img_gray,mask,patch_size);%% ========== 3. 结果可视化 ==========figure('Color','white','Position',[1001001200400])subplot(1,3,1)imshow(img_gray)title('原始图像')subplot(1,3,2)imshow(broken_img)title('破损图像(中心矩形区域)')subplot(1,3,3)imshow(inpainted_img)title(sprintf('Criminisi修复结果(块大小=%d)',patch_size))%% ========== 4. (可选)计算修复质量指标 ==========% 如果有原始完整图像,可以计算PSNRpsnr_val=psnr(inpainted_img,img_gray);fprintf('修复图像PSNR: %.2f dB\n',psnr_val);

参考代码 图像修复算法www.youwenfan.com/contentcsw/82890.html

三、关键参数说明

参数作用推荐值
patch_size修复块大小9/11/15(纹理越丰富,块越大;结构越简单,块越小)
max_iter最大迭代次数1000(破损区域大时适当增大)
掩码制作定义破损区域用画图工具手动标注,或代码生成(矩形/圆形/自定义形状)

四、彩色图像修复方法

上面的代码是灰度图版本,彩色图像修复有两种常用方案:

方案1:逐通道修复(简单但可能颜色失真)

img_color=imread('lena.png');mask=imread('mask.png');inpainted_color=zeros(size(img_color));forc=1:3[inpainted_color(:,:,c),~]=criminisi_inpaint(img_color(:,:,c),mask,9);end

方案2:HSV空间修复(推荐,颜色更自然)

img_hsv=rgb2hsv(img_color);% 只在V(明度)通道修复,H(色调)和S(饱和度)保持不变[V_inpainted,~]=criminisi_inpaint(img_hsv(:,:,3),mask,9);img_hsv(:,:,3)=V_inpainted;inpainted_color=hsv2rgb(img_hsv);

五、算法优缺点

优点

  • 擅长修复大面积纹理/结构破损(如移除照片中的路人、修复划痕)
  • 能保持结构的连续性,修复结果更符合人类视觉习惯
  • 无需训练数据,通用性强

缺点

  • 计算量大(全图搜索匹配块,512x512图像约需1-5分钟)
  • 平滑区域容易出现块效应
  • 对复杂语义(如人脸五官)修复效果差

六、与其他修复算法的对比

算法适用场景优缺点
Criminisi大面积纹理/结构破损结构保持好,速度慢
TV-Inpainting小面积平滑区域破损速度快,纹理模糊
PatchMatch纹理合成速度快,结构保持弱
深度学习(LaMa/Stable Diffusion)复杂语义破损效果好,需要训练数据

如果你的破损区域是不规则形状(如划痕、文字遮挡),可以告诉我,我帮你修改掩码生成代码;如果是彩色图像/实时性要求高,也可以给你对应的优化版本。

http://www.cnnetsun.cn/news/3240161.html

相关文章:

  • 西安出境欧洲多国联游纯玩无自费旅游业务 | 公司品牌名称
  • 解锁B站个性化新体验:Bilibili-Evolved完全使用指南
  • 终极指南:如何使用网盘直链下载助手实现九大网盘高速下载
  • 网盘直链下载助手:打破网盘限速壁垒的终极解决方案
  • Codex 本地 AI 编程助手十六维锐评:从安装到实战,避坑指南与场景适配
  • D3KeyHelper完全指南:5分钟打造你的暗黑3专属按键助手
  • D3KeyHelper:5分钟掌握暗黑破坏神3终极自动化按键助手
  • 学术写作效率突破!2026全流程AI写作辅助软件深度解析
  • 终极免费方案:如何永久保存你的微信聊天记录完整备份
  • 让中学生也能一下子认识中学数学几百年重大错误:R各元x的对应数2x的全体=R
  • FastAPI 静态文件:Web 页面的“固定展柜”与“加速引擎”
  • 企业智能AI落地实战:从工具到生产力的三步走
  • 混元Hy3正式发布,腾讯的长期主义有了效果
  • CircuitJS1:你的个人电子实验室,随时随地探索电路奥秘
  • 植物大战僵尸终极改造指南:PvZ Toolkit完全解析
  • 5分钟掌握:如何永久激活你的Windows和Office系统
  • AI工程师转型路径04-AI应用开发岗技能图谱——普通程序员最容易切入的赛道
  • 网络安全实战能力进阶:从DVWA到SRC的靶场训练全路径指南
  • Magpie完整指南:如何让老旧窗口在4K屏幕上焕发新生
  • Cyber Weekly #71
  • 深度解析PyQt6:5大核心模块构建现代Python桌面应用
  • OpenResty 1.25.3.1 升级实战:CentOS 7.9 平滑迁移与 5 个 Lua 模块兼容性验证
  • 兴庆区靠谱的配镜眼科诊所
  • VASPsol终极指南:如何在DFT计算中轻松处理溶剂化效应 [特殊字符]
  • 宁夏靠谱的配镜眼科诊所
  • UE5 C++文件系统深度解析:从IPlatformFile到蓝图库的完整实践
  • BsMax:Blender中的3ds Max工作流模拟器架构解析
  • 成都版权登记办理中心挑选指南 核心维度与五家服务商解析
  • 番茄小说永久保存终极指南:告别内容丢失的完整解决方案
  • AI TVC赋能工业营销 集之互动以工业级影像助力制造品牌价值升级