一、算法实现代码
%% Criminisi 图像修复算法(支持彩色图像)
% 功能:修复图像中的缺失区域(如划痕、遮挡物)
clear; clc; close all;
%% 参数设置
imgPath = 'damaged_image.jpg'; % 输入图像路径
maskPath = 'mask.png'; % 缺失区域掩膜(白色为缺失)
patchSize = 9; % 修复块大小(奇数)
searchWin = 50; % 搜索窗口大小
maxIter = 1000; % 最大迭代次数
%% 读取图像与掩膜
img = imread(imgPath);
if size(img,3) == 1
img = cat(3, img, img, img); % 转换为 RGB 格式
end
mask = imbinarize(im2double(imread(maskPath))); % 二值化掩膜
%% 初始化参数
[h,w,~] = size(img);
confidence = double(~mask); % 置信度图(已知区域=1)
isFixed = false(h,w); % 固定点标记
fixedPts = detectBoundary(mask); % 检测边界点作为初始修复点
%% 主循环
tic;
for iter = 1:maxIter
if isempty(fixedPts)
break;
end
% 选择优先级最高的点
[p, fixedPts] = selectPriorityPoint(img, mask, confidence, fixedPts);
% 搜索最佳匹配块
[bestX, bestY] = findBestMatch(img, mask, p, patchSize, searchWin);
% 执行修复
[img, mask, confidence] = inpaintBlock(img, mask, confidence, bestX, bestY, patchSize);
% 更新进度
fprintf('Iteration %d: Repaired %d points\n', iter, size(fixedPts,1));
end
toc;
%% 结果可视化
figure;
subplot(1,2,1);
imshow(img);
title('原始图像');
subplot(1,2,2);
imshow(mask);
title('缺失区域掩膜');
figure;
imshow(img);
title('修复结果');
%% 核心函数定义
function fixedPts = detectBoundary(mask)
% 检测掩膜边界点作为初始修复点
[rows,cols] = find(mask);
boundaryPts = [];
for i = 1:length(rows)
% 获取 8 邻域
neighbors = [rows(i)+(-1:1), cols(i)+(-1:1)];
valid = neighbors(all(neighbors > 0 & neighbors <= size(mask)), :);
if any(mask(valid(:,1), valid(:,2)) == 0)
boundaryPts = [boundaryPts; rows(i), cols(i)];
end
end
fixedPts = boundaryPts;
end
function [p, fixedPts] = selectPriorityPoint(img, mask, confidence, fixedPts)
% 选择优先级最高的点
if isempty(fixedPts)
[~,idx] = max(confidence(:));
p = ind2sub(size(confidence), idx);
return;
end
% 计算数据项(梯度方向)
[Gx,Gy] = gradient(double(rgb2gray(img)));
G = cat(3, Gx, Gy);
normals = cat(3, -Gy, Gx);
% 等照度线法向量
maxP = -inf;
p = [0,0];
for i = 1:size(fixedPts,1)
y = fixedPts(i,1);
x = fixedPts(i,2);
% 计算法向量
if y==1 || y==size(img,1) || x==1 || x==size(img,2)
n = normals(:,:,1); % 边界处法向量
else
n = normals(y,x,:);
end
% 计算数据项
patch = getPatch(img, x,y,patchSize);
knownPatch = getPatch(img, x,y,patchSize).*double(~mask);
D = 1 - ssim(knownPatch, patch); % 计算优先级
C = mean(confidence(max(1,y-floor(patchSize/2)):min(size(img,1),y+floor(patchSize/2)),...
max(1,x-floor(patchSize/2)):min(size(img,2),x+floor(patchSize/2))));
P = C * D;
if P > maxP
maxP = P;
p = [y,x];
end
end
end
function [bestX, bestY] = findBestMatch(img, mask, p, patchSize, searchWin)
% 在搜索窗口内寻找最佳匹配块
[h,w] = size(img);
y = p(1);
x = p(2);
% 定义搜索范围
yMin = max(1, y-floor(searchWin/2));
yMax = min(h, y+floor(searchWin/2));
xMin = max(1, x-floor(searchWin/2));
xMax = min(w, x+floor(searchWin/2));
minSSD = inf;
bestY = y;
bestX = x;
for yy = yMin:yMax
for xx = xMin:xMax
if mask(yy,xx) == 1
continue; % 跳过缺失区域
end
% 计算 SSD
targetPatch = getPatch(img, y,x,patchSize);
candPatch = getPatch(img, yy,xx,patchSize);
maskPatch = double(mask(y-floor(patchSize/2):y+floor(patchSize/2),...
x-floor(patchSize/2):x+floor(patchSize/2)));
ssd = sum(sum((targetPatch - candPatch).^2.*(1-maskPatch)));
if ssd < minSSD
minSSD = ssd;
bestY = yy;
bestX = xx;
end
end
end
end
function [img, mask, confidence] = inpaintBlock(img, mask, confidence, x, y, patchSize)
% 修复块操作
halfPatch = floor(patchSize/2);
yMin = max(1, y-halfPatch);
yMax = min(size(img,1), y+halfPatch);
xMin = max(1, x-halfPatch);
xMax = min(size(img,2), x+halfPatch);
% 复制匹配块内容
targetPatch = getPatch(img, y,x,patchSize);
maskPatch = double(mask(yMin:yMax, xMin:xMax));
img(yMin:yMax, xMin:xMax,:) = img(yMin:yMax, xMin:xMax,:).*(1-maskPatch) + ... targetPatch .* maskPatch;
% 更新置信度
confidence(yMin:yMax, xMin:xMax) = confidence(yMin:yMax, xMin:xMax)*0.9;
confidence(y,x) = 1; % 新修复点置信度设为 1
% 更新掩膜
mask(yMin:yMax, xMin:xMax) = 0;
end
function patch = getPatch(img, x, y, patchSize)
% 提取图像块
half = floor(patchSize/2);
yMin = max(1, y-half);
yMax = min(size(img,1), y+half);
xMin = max(1, x-half);
xMax = min(size(img,2), x+half);
patch = img(yMin:yMax, xMin:xMax,:);
end