本文目录导读:

我来详细讲解Python实现图像修复的几种方法,从基础到进阶。
使用OpenCV的修复函数(最简单)
基于邻域修复(INPAINT_TELEA)
import cv2
import numpy as np
import matplotlib.pyplot as plt
def basic_inpainting():
# 读取图像
img = cv2.imread('damaged_image.jpg')
# 创建掩膜(需要修复的区域标记为白色)
mask = cv2.imread('mask.jpg', 0) # 灰度图
# 或者手动创建掩膜
# mask = np.zeros(img.shape[:2], np.uint8)
# mask[100:200, 100:200] = 255 # 标记需要修复的区域
# 图像修复
result_telea = cv2.inpaint(img, mask, 3, cv2.INPAINT_TELEA)
result_ns = cv2.inpaint(img, mask, 3, cv2.INPAINT_NS)
# 显示结果
plt.figure(figsize=(15, 5))
plt.subplot(131)
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.title('原始图像')
plt.axis('off')
plt.subplot(132)
plt.imshow(cv2.cvtColor(result_telea, cv2.COLOR_BGR2RGB))
plt.title('Telea算法修复')
plt.axis('off')
plt.subplot(133)
plt.imshow(cv2.cvtColor(result_ns, cv2.COLOR_BGR2RGB))
plt.title('Navier-Stokes算法修复')
plt.axis('off')
plt.tight_layout()
plt.show()
basic_inpainting()
交互式选择修复区域
import cv2
import numpy as np
class InteractiveInpainting:
def __init__(self, image_path):
self.img = cv2.imread(image_path)
self.mask = np.zeros(self.img.shape[:2], np.uint8)
self.drawing = False
self.brush_size = 10
def draw_mask(self, event, x, y, flags, param):
if event == cv2.EVENT_LBUTTONDOWN:
self.drawing = True
cv2.circle(self.mask, (x, y), self.brush_size, 255, -1)
elif event == cv2.EVENT_MOUSEMOVE and self.drawing:
cv2.circle(self.mask, (x, y), self.brush_size, 255, -1)
elif event == cv2.EVENT_LBUTTONUP:
self.drawing = False
def run(self):
cv2.namedWindow('Mask Drawing')
cv2.setMouseCallback('Mask Drawing', self.draw_mask)
while True:
display = self.img.copy()
display[self.mask == 255] = [0, 0, 255] # 标记为红色
cv2.imshow('Mask Drawing', display)
key = cv2.waitKey(1) & 0xFF
if key == ord('r'): # 重置
self.mask = np.zeros(self.img.shape[:2], np.uint8)
elif key == ord('+'): # 增大笔刷
self.brush_size += 2
elif key == ord('-'): # 减小笔刷
self.brush_size = max(1, self.brush_size - 2)
elif key == ord('p'): # 执行修复
result = cv2.inpaint(self.img, self.mask, 3, cv2.INPAINT_TELEA)
cv2.imshow('Result', result)
elif key == ord('s'): # 保存
result = cv2.inpaint(self.img, self.mask, 3, cv2.INPAINT_TELEA)
cv2.imwrite('repaired_image.jpg', result)
print("图像已保存")
elif key == 27: # ESC退出
break
cv2.destroyAllWindows()
# 使用交互式工具
# repair = InteractiveInpainting('damaged_image.jpg')
# repair.run()
自动检测并修复缺陷
import cv2
import numpy as np
from skimage import restoration, morphology
def auto_detect_and_repair(image_path):
# 读取图像
img = cv2.imread(image_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 方法1:使用边缘检测找出缺陷
edges = cv2.Canny(gray, 50, 150)
kernel = np.ones((5,5), np.uint8)
dilated = cv2.dilate(edges, kernel, iterations=2)
# 创建掩膜
mask = dilated.copy()
# 方法2:使用阈值检测暗区域
_, thresh = cv2.threshold(gray, 30, 255, cv2.THRESH_BINARY_INV)
mask = cv2.bitwise_or(mask, thresh)
# 清理掩膜
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
# 图像修复
result = cv2.inpaint(img, mask, 3, cv2.INPAINT_TELEA)
return img, mask, result
# 使用示例
original, mask, repaired = auto_detect_and_repair('old_photo.jpg')
# 显示结果
plt.figure(figsize=(15, 5))
plt.subplot(131), plt.imshow(cv2.cvtColor(original, cv2.COLOR_BGR2RGB)), plt.title('原始图像')
plt.subplot(132), plt.imshow(mask, cmap='gray'), plt.title('检测到的缺陷')
plt.subplot(133), plt.imshow(cv2.cvtColor(repaired, cv2.COLOR_BGR2RGB)), plt.title('修复结果')
plt.show()
使用深度学习方法(PatchMatch算法)
import numpy as np
import cv2
from scipy import ndimage
class PatchMatchInpainting:
def __init__(self, patch_size=7):
self.patch_size = patch_size
self.half_patch = patch_size // 2
def get_patch(self, img, y, x):
"""获取图像块"""
return img[y-self.half_patch:y+self.half_patch+1,
x-self.half_patch:x+self.half_patch+1]
def patch_distance(self, patch1, patch2, mask_patch):
"""计算两个patch之间的距离(只考虑已知像素)"""
diff = (patch1 - patch2) ** 2
diff = diff * mask_patch
return np.sum(diff) / max(np.sum(mask_patch), 1)
def inpaint(self, image, mask):
"""执行基于PatchMatch的图像修复"""
img = image.copy().astype(np.float32)
h, w = img.shape[:2]
# 找到需要修复的像素
unknown_pixels = np.where(mask == 255)
# 对于每个需要修复的像素
for i in range(len(unknown_pixels[0])):
y, x = unknown_pixels[0][i], unknown_pixels[1][i]
# 跳过边缘像素
if (y < self.half_patch or y >= h - self.half_patch or
x < self.half_patch or x >= w - self.half_patch):
continue
# 获取目标patch
target_patch = self.get_patch(img, y, x)
target_mask = self.get_patch(mask.astype(np.float32), y, x)
target_mask = 1 - target_mask / 255 # 未知区域为1
best_patch = None
best_distance = float('inf')
# 搜索最佳匹配patch
for sy in range(self.half_patch, h - self.half_patch, 2):
for sx in range(self.half_patch, w - self.half_patch, 2):
# 跳过未知区域
if mask[sy, sx] == 255:
continue
source_patch = self.get_patch(img, sy, sx)
distance = self.patch_distance(target_patch, source_patch, target_mask)
if distance < best_distance:
best_distance = distance
best_patch = source_patch
# 用最佳匹配填充
if best_patch is not None:
for c in range(3):
img[y-self.half_patch:y+self.half_patch+1,
x-self.half_patch:x+self.half_patch+1, c] = best_patch[:, :, c]
return img.astype(np.uint8)
# 使用PatchMatch修复
def patchmatch_demo():
img = cv2.imread('damaged_image.jpg')
mask = cv2.imread('mask.jpg', 0)
# 确保掩膜是二值图
_, mask = cv2.threshold(mask, 127, 255, cv2.THRESH_BINARY)
# 执行修复
pm_inpainting = PatchMatchInpainting(patch_size=7)
result = pm_inpainting.inpaint(img, mask)
# 显示结果
plt.figure(figsize=(15, 5))
plt.subplot(131), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title('原始图像')
plt.subplot(132), plt.imshow(mask, cmap='gray'), plt.title('掩膜')
plt.subplot(133), plt.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB)), plt.title('PatchMatch修复')
plt.show()
# patchmatch_demo()
使用scikit-image的修复函数
from skimage import restoration, io, color
import matplotlib.pyplot as plt
def skimage_inpainting():
# 读取图像
image = io.imread('damaged_image.jpg')
mask = io.imread('mask.png', as_gray=True)
# 转换为浮点型
image_float = image.astype(float) / 255.0
# 如果是彩色图像,分别处理每个通道
if len(image_float.shape) == 3:
result = np.zeros_like(image_float)
for channel in range(3):
result[:,:,channel] = restoration.inpaint_biharmonic(
image_float[:,:,channel],
mask > 0.5,
multichannel=False
)
else:
result = restoration.inpaint_biharmonic(
image_float,
mask > 0.5
)
return image, result
original, repaired = skimage_inpainting()
完整的图像修复工具类
import cv2
import numpy as np
from enum import Enum
class InpaintingMethod(Enum):
TELEA = 1
NAVIER_STOKES = 2
PATCH_MATCH = 3
class ImageRepairTool:
def __init__(self):
self.methods = {
InpaintingMethod.TELEA: cv2.INPAINT_TELEA,
InpaintingMethod.NAVIER_STOKES: cv2.INPAINT_NS
}
def create_mask_from_text(self, image, text="", position=(50, 50)):
"""在图像上添加文字作为需要修复的区域"""
mask = np.zeros(image.shape[:2], np.uint8)
if text:
font = cv2.FONT_HERSHEY_SIMPLEX
text_size = cv2.getTextSize(text, font, 1, 2)[0]
cv2.putText(mask, text, position, font, 1, 255, 2)
return mask
def remove_object(self, image, bbox):
"""移除指定边界框内的物体"""
x, y, w, h = bbox
mask = np.zeros(image.shape[:2], np.uint8)
mask[y:y+h, x:x+w] = 255
return mask
def repair(self, image, mask, method=InpaintingMethod.TELEA, radius=3):
"""执行图像修复"""
if method in [InpaintingMethod.TELEA, InpaintingMethod.NAVIER_STOKES]:
return cv2.inpaint(image, mask, radius, self.methods[method])
else:
# 使用PatchMatch
pm = PatchMatchInpainting()
return pm.inpaint(image, mask)
def batch_repair(self, image_paths, mask_paths, output_dir):
"""批量修复图像"""
import os
os.makedirs(output_dir, exist_ok=True)
for img_path, mask_path in zip(image_paths, mask_paths):
img = cv2.imread(img_path)
mask = cv2.imread(mask_path, 0)
result = self.repair(img, mask)
output_path = os.path.join(output_dir,
f"repaired_{os.path.basename(img_path)}")
cv2.imwrite(output_path, result)
print(f"已修复: {img_path}")
# 使用示例
def demo_full_tool():
tool = ImageRepairTool()
# 读取图像
img = cv2.imread('photo.jpg')
# 方法1:去除文字
mask_text = tool.create_mask_from_text(img, "Remove this text")
result1 = tool.repair(img, mask_text)
# 方法2:去除物体
mask_object = tool.remove_object(img, (50, 50, 100, 100))
result2 = tool.repair(img, mask_object, InpaintingMethod.NAVIER_STOKES)
# 显示结果
plt.figure(figsize=(15, 5))
plt.subplot(131), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.title('原始图像')
plt.subplot(132), plt.imshow(cv2.cvtColor(result1, cv2.COLOR_BGR2RGB))
plt.title('去除文字')
plt.subplot(133), plt.imshow(cv2.cvtColor(result2, cv2.COLOR_BGR2RGB))
plt.title('去除物体')
plt.show()
# demo_full_tool()
使用建议
- 简单修复:使用OpenCV的
cv2.inpaint()函数 - 交互式修复:创建GUI让用户手动标记修复区域
- 批量处理:使用上述工具类处理多张图像
- 深度学习:对于复杂情况,考虑使用OpenCV的DNN模块或PyTorch
安装依赖
pip install opencv-python numpy matplotlib scikit-image scipy
选择哪种方法取决于:
- 修复区域的复杂度
- 图像质量要求
- 处理速度需求
- 是否需要交互操作
对于大多数日常使用,OpenCV内置的修复函数已经足够好用。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播