OpenCV图像修复cv2.inpaint()的使用
作者:程序媛一枚~ 发布时间:2022-07-03 05:47:57
这篇博客将介绍如何通过OpenCV中图像修复的技术——cv2.inpaint() 去除旧照片中的小噪音、笔划等。并提供一个可交互式的程序,利用OpenCV的快速行进和流体力学俩种修复算法对自己的图片进行修复。
大多数人家里都会有一些旧的老化照片,上面有一些黑点、笔划等。如何复原呢?
在绘制工具中擦除:将简单地用无用的白色结构替换黑色结构,效果并不理想。OpenCV中图像修复的技术——基本思想很简单:用相邻像素替换这些坏标记,使其看起来像邻居。
cv2.INPAINT_TELEA(Fast Marching Method 快速行进算法)
cv2.INPAINT_NS(Fluid Dynamics Method 流体力学算法)
OpenCV未实现的:Content-Aware Fill 内容感知填充算法,这是Adobe Photoshop中使用的一种高级修复技术。
cv2.inpaint() 优点:修复效果更加自然;
缺点:修复时需要提供原图以及mask图(与原图一致只有被污染的像素区域有值);
1. 效果图
官方原始图 VS mask图 VS 快速行进算法修复效果 VS 流体力学修复效果 如下:
接下来用可交互的例子实现自己的图片修复;
原始图 VS Mask图 VS 快速行进算法修复效果图如下:
原始图随意用鼠标左键移动绘制点、线,右键移动绘制矩形来随机增加一些被污染的区域;
并根据原始图生成mask图,mask图是与原始图具有相同大小,并且只有被污染的区域是白色像素的图。可以看到修复效果还是挺好的~
原始图 VS Mask图 VS 流体力学算法修复效果图如下:
原始图随意用鼠标左键移动绘制点、线,右键移动绘制矩形来随机增加一些被污染的区域;
mask图是与原始图具有相同大小,并且只有被污染的区域是白色像素的图。可以看到修复效果还是挺好的~
快速行进算法与流体力学算法修复的效果图差别不太大;
2. 原理
cv2.INPAINT_TELEA (Fast Marching Method 快速行进算法),对位于点附近、边界法线附近和边界轮廓上的像素赋予更多权重。一旦一个像素被修复,它将使用快速行进的方法移动到下一个最近的像素。
cv2.INPAINT_NS(Fluid Dynamics Method 流体力学算法),使用了流体力学的一些方法,基本原则是启发式的。首先沿着边从已知区域移动到未知区域(因为边是连续的)。它在匹配修复区域边界处的渐变向量的同时,继续等高线(连接具有相同强度的点的线,就像等高线连接具有相同高程的点一样)。
OpenCV未实现的:Content-Aware Fill 内容感知填充算法,这是Adobe Photoshop中使用的一种高级修复技术。
3. 源码
# 图像修复交互式案例——通过水流填充算法来修复被破坏的图像区域;
# 使用俩种方法进行修复
# cv2.INPAINT_TELEA (Fast Marching Method 快速行进算法),对位于点附近、边界法线附近和边界轮廓上的像素赋予更多权重。一旦一个像素被修复,它将使用快速行进的方法移动到下一个最近的像素。
# cv2.INPAINT_NS 流体力学算法,使用了流体力学的一些方法,基本原则是启发式的,首先沿着边从已知区域移动到未知区域(因为边是连续的)。它在匹配修复区域边界处的渐变向量的同时,继续等高线(连接具有相同强度的点的线,就像等高线连接具有相同高程的点一样)。
# USAGE
# python inpaint.py D:/deepLearning/py-demo/20210808/images/ml.jpg
# 按下鼠标左键,添加点、线,按下鼠标右键,添加矩形框,以制作被污染的需要修复图像
# 按下空格键:执行修复功能
# 按下r键:重置待修复的mask
# 按下esc键,退出
import cv2
import numpy as np
class Sketcher:
def __init__(self, windowname, dests, colors_func):
self.prev_pt = None # 线起始点
self.drag_start = None # 矩形起点
self.drag_rect = None # 矩形(左上角,右下角)坐标
self.windowname = windowname
self.dests = dests
self.colors_func = colors_func
self.dirty = False
self.drawing = False
self.mode = False
self.show()
cv2.setMouseCallback(self.windowname, self.on_mouse)
def show(self):
cv2.imshow(self.windowname, self.dests[0])
def on_mouse(self, event, x, y, flags, param):
pt = (x, y)
if event == cv2.EVENT_LBUTTONDOWN:
self.prev_pt = pt
self.drawing = True
elif event == cv2.EVENT_RBUTTONDOWN:
# 第一次初始化时设定pt,往后保留上一个点作为矩形起点
if self.drag_start == None:
self.drag_start = pt
if self.prev_pt and flags & cv2.EVENT_FLAG_LBUTTON:
for dst, color in zip(self.dests, self.colors_func()):
cv2.line(dst, self.prev_pt, pt, color, 5)
self.dirty = True
self.prev_pt = pt
self.show()
if self.drag_start and flags & cv2.EVENT_FLAG_RBUTTON:
xo, yo = self.drag_start
x0, y0 = np.minimum([xo, yo], [x, y])
x1, y1 = np.maximum([xo, yo], [x, y])
self.drag_rect = None
if x1 - x0 > 0 and y1 - y0 > 0:
self.drag_rect = (x0, y0, x1, y1)
for dst, color in zip(self.dests, self.colors_func()):
cv2.rectangle(dst, (x0, y0), (x1, y1), color, -1)
self.dirty = True
self.drag_start = None
self.drag_rect = None
self.show()
else:
self.drag_start = pt
@property
def dragging(self):
return self.drag_rect is not None
def main():
import sys
try:
fn = sys.argv[1]
except:
fn = 'images/ml_.jpg'
img = cv2.imread(fn)
if img is None:
print('Failed to load image file:', fn)
sys.exit(1)
img_mark = img.copy()
mark = np.zeros(img.shape[:2], np.uint8)
sketch = Sketcher('img', [img_mark, mark], lambda: ((255, 255, 255), 255))
while True:
ch = cv2.waitKey()
if ch == 27:
break
if ch == ord(' '):
cv2.imshow('mask', mark)
fmmres = cv2.inpaint(img_mark, mark, 3, cv2.INPAINT_TELEA)
nsres = cv2.inpaint(img_mark, mark, 3, cv2.INPAINT_NS)
cv2.imshow('inpaint fmm res', fmmres)
cv2.imshow('inpaint ns res', nsres)
if ch == ord('r'):
img_mark[:] = img
mark[:] = 0
sketch.show()
print('Done')
if __name__ == '__main__':
main()
cv2.destroyAllWindows()
参考 https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_photo/py_inpainting/py_inpainting.html#inpainting
来源:https://blog.csdn.net/qq_40985985/article/details/119508318
猜你喜欢
- 这篇文章主要介绍了python next()和iter()函数原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学
- 本文实例讲述了Python中itertools模块用法,分享给大家供大家参考。具体分析如下:一般来说,itertools模块包含创建有效迭代
- 问题:连续或者单个窗体,如何打印当前显示的记录?当前窗体还有对应的子窗体,也要一起打印出来我在一个窗体里有一个单号,大子窗体里有几组数据,我
- py文件为utf-8格式#!/usr/bin/env python# -*- coding:utf-8 -*-a = "syste
- 环境: Python3 + windows。开发工具:Anaconda + Jupyter / VS Code。学习效果:1.认识爬虫 /
- 有时候,我们需要在字符串中加入相应的变量,以下提供了几种字符串加入变量的方法:1、+ 连字符name = 'zhangsan'
- 之前在做数据分析的过程中,需要对数据进行实时的写入,比如对新生成的数据写入之前已经生成的txt或csv文件中。现在想想其实很简单,所以做一个
- 如果你是一位ASP爱好者,你一定想过ASP的执行效率如何?大家都知道ASP效率和CGI的比,在访问量少的时候,它们是不相上下的,有时可能CG
- 看lifesinger的《由Kimi找茬想到的》,我想到的:1、 我不同意将“合并付款”定调在“很多卖家都需要”。这个“很多”在卖家里面大概
- 生成方式Python中想要自动生成 model文件可以通过 sqlacodegen这个命令来生成对应的model文件sqlacodegen
- 又从 James Padolsey 这里得到个好的点子。在实际写脚本过程中可能有段 Javascript 和 HTML 非常相关(比如实例化
- 环境:python3.6 pyqt5只是简单的一个思路,请忽略脆弱的异常防护:# -*- coding: utf-8 -*-import s
- 前言:二分法也就是二分查找,它是一种效率较高的查找方法假如公司新来了一个人,叫张三,他是你们公司第47个人,过了一段时间后,有些人呢看张三不
- Django处理Ajax发送的Get请求实例,Ajax优点在一是异步请求,无需等待响应就可以再次发起请求,而是局部刷新,避免整个页面刷新的网
- 为什么选择Python进行数据分析?Python是一门动态的、面向对象的脚本语言,同时也是一门简约,通俗易懂的编程语言。Python入门简单
- 有一些问题可能会遇到同元素多列去重问题,下面介绍一种非常简单效率也很快的做法,用pandas来实现。首先我们看一下数据类型:G1 G2a b
- 这个函数是前几年刚流行小偷程序的时候,偶写来用于小偷程序中截取代码的;可能有些朋友在我以前的代码中看见过了,但没有写用法,现在把调用方法及使
- linux平台及windows平台mysql重启方 * inux下重启MySQL的正确方法:1、通过rpm包安装的MySQLservice m
- 免费手机号码归属地API查询接口和PHP使用实例分享最近在做全国性的行业分类信息网站,需要用到手机号归属地显示功能,于是就穿梭于各大权威站点
- 本文实例为大家分享了python实现在线翻译的具体代码,供大家参考,具体内容如下具体效果请看图代码:import urllib.reques