OpenCV圖像修復cv2.inpaint()的使用
這篇博客將介紹如何通過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
到此這篇關於OpenCV圖像修復cv2.inpaint()的使用的文章就介紹到這瞭,更多相關OpenCV圖像修復cv2.inpaint()內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Python-OpenCV中的cv2.inpaint()函數的使用
- Android基於OpenCV實現圖像修復
- OpenCV學習之圖像的分割與修復詳解
- OpenCV利用對比度亮度變換實現水印去除
- Python OpenCV基於HSV的顏色分割實現示例