OpenCV快速入門:圖像分析——圖像分割和圖像修復

文章目錄

  • 前言
  • 一、圖像分割
    • 1.1 漫水填充法
      • 1.1.1 漫水填充法原理
      • 1.1.2 漫水填充法實現步驟
      • 1.1.3 代碼實現
    • 1.2 分水嶺法
      • 1.2.1 分水嶺法原理
      • 1.2.2 分水嶺法實現步驟
      • 1.2.3 代碼實現
    • 1.3 GrabCut法
      • 1.3.1 GrabCut法原理
      • 1.3.2 GrabCut法實現步驟
      • 1.3.3 代碼實現
    • 1.4 Mean-Shift法
      • 1.4.1 Mean-Shift法原理
      • 1.4.2 Mean-Shift法實現步驟
      • 1.4.3 代碼實現
  • 二、圖像修復
    • 2.1 圖像修復原理
      • 2.1.1 Telea方法
      • 2.1.2 Navier-Stokes方法
      • 2.1.3 代碼實現
    • 2.2 修補算法
      • 2.2.1 修補算法原理
      • 2.2.2 修補算法實現步驟
      • 2.2.3 OpenCV代碼實現
        • 2.2.3.1 方形補丁修補
        • 2.2.3.2 圓形補丁修補
  • 總結

前言

OpenCV(Open Source Computer Vision Library)作為一個開源的計算機視覺和機器學習軟件庫,提供了豐富的圖像處理功能,使得圖像分析變得更加高效和易于實現。本篇博客旨在提供一個關于OpenCV中圖像分割和圖像修復技術的入門指南,從基本原理到代碼實現,簡要覆蓋這些技術的關鍵方面。
opencv logo

一、圖像分割

圖像分割是圖像處理中的一項重要技術,它涉及將圖像劃分為多個部分或區域,以便更容易地分析和處理。

1.1 漫水填充法

1.1.1 漫水填充法原理

漫水填充 (Flood Fill)算法基于區域生長的概念。它從圖像中的一個點(種子點)開始,然后向所有與該點相連的、顏色/強度相似的區域擴展。

1.1.2 漫水填充法實現步驟

  1. 選擇一個種子點。
  2. 檢查相鄰像素是否屬于同一區域(基于顏色/強度相似度)。
  3. 如果相鄰像素符合條件,則包括它,并繼續向外擴展。
  4. 重復此過程直到無法擴展。

1.1.3 代碼實現

import cv2
import numpy as np# 讀取圖像
image = cv2.imread('tulips.jpg')
# 創建一個與圖像大小相同的掩碼(mask),并初始化為全0
mask = np.zeros((image.shape[0] + 2, image.shape[1] + 2), dtype=np.uint8)# 定義填充的起始點
start_point1 = (100, 100)  # 開始填充的坐標
start_point2 = (420, 200)  # 開始填充的坐標
# 定義填充顏色
fill_color = (0, 0, 0)  # 黑色
# 定義顏色容差范圍
tolerance = (160, 160, 160, 160)  # 上下左右的容差# floodFill函數的參數
flood_fill_flags = 4
flood_fill_flags |= 255 << 8
flood_fill_flags |= cv2.FLOODFILL_FIXED_RANGE# 調用floodFill函數
image_fill = image.copy()
cv2.floodFill(image_fill, mask, start_point1, fill_color, tolerance, tolerance, flood_fill_flags)
cv2.floodFill(image_fill, mask, start_point2, fill_color, tolerance, tolerance, flood_fill_flags)# 顯示結果
mask_img = cv2.merge([mask,mask,mask])
# 獲取圖像的高度和寬度
height, width ,channel= image.shape
# 創建一個新的圖像,高度和寬度各增加一
new_height = height + 2
new_width = width + 2
image_origin = np.zeros((new_height, new_width, channel), dtype=np.uint8)
# 將原始圖像復制到新圖像中
image_origin[:height, :width] = imageimage_flood = np.zeros((new_height, new_width, channel), dtype=np.uint8)
# 將原始圖像復制到新圖像中
image_flood[:height, :width] = image_fillcv2.imshow('Flood Filled Image', cv2.hconcat([image_origin,image_flood, mask_img]))
cv2.waitKey(0)
cv2.destroyAllWindows()

Flood Filled Image
cv2.floodFill 函數用于實現漫水填充算法,即填充一個連通區域的顏色或圖案。這個函數非常適合于圖像分割、對象檢測和圖像編輯等任務。下面是對 cv2.floodFill 函數參數和功能的簡要介紹:

def floodFill(image, mask, seedPoint, newVal, loDiff=None, upDiff=None, flags=None)

  1. image: 輸入/輸出圖像。這是一個單通道或三通道的8位或浮點圖像。除非設置了 FLOODFILL_MASK_ONLY 標志,否則此函數會修改輸入圖像。

  2. mask: 操作掩碼,應該是一個單通道8位圖像,比輸入圖像寬2個像素,高2個像素。這是一個輸入和輸出參數,因此在使用前需要初始化。漫水填充不能穿過掩碼中非零的像素。例如,邊緣檢測器的輸出可以作為掩碼,以阻止填充穿過邊緣。

  3. seedPoint: 開始點。這是漫水填充開始的像素位置。

  4. newVal: 重新繪制域像素的新值。

  5. loDiffupDiff: 分別代表最大下限和上限的亮度/顏色差異。這些參數決定了填充顏色與周圍像素顏色的最大允許差異。

  6. rect: 可選的輸出參數,函數設置為重新繪制域的最小邊界矩形。

  7. flags: 操作標志。前8位包含連接值,4代表只考慮四個最近鄰像素(那些共享邊的像素),8代表將考慮八個最近鄰像素(那些共享角的像素)。接下來的8位(8-16位)包含用來填充掩碼的值(默認值為1)。例如,4 | (255 << 8) 將考慮4個最近鄰居,并用255的值填充掩碼。

這個函數通過比較像素與其鄰居或種子點的顏色/亮度差異來確定哪些像素屬于同一連接組件,并將這些像素填充為新的顏色或值。在實際應用中,需要根據具體的圖像和需求調整參數,以達到最佳的填充效果。

1.2 分水嶺法

1.2.1 分水嶺法原理

分水嶺(Watershed)算法模擬地理學中的水流原理。在圖像中,任何灰度值可以看作高度,算法模擬雨水流入低洼地區,形成不同的“湖泊”,每個湖泊代表圖像的一個分割區域。

1.2.2 分水嶺法實現步驟

  1. 對圖像應用邊緣檢測,例如使用Canny算法。
  2. 應用距離變換。
  3. 應用分水嶺算法分割圖像。

1.2.3 代碼實現

import cv2
import numpy as np# 讀取圖像
image = cv2.imread('tulips.jpg')
# 轉換為灰度圖
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 應用閾值化來標記前景區域
_, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)# 去除噪聲
kernel = np.ones((7, 7), np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=2)# 確定背景區域
sure_bg = cv2.dilate(opening, kernel, iterations=6)
# 確定前景區域
dist_transform = cv2.distanceTransform(opening, cv2.DIST_L2, 5)
_, sure_fg = cv2.threshold(dist_transform, 0.8 * dist_transform.max(), 255, 0)# 找到未知區域
sure_fg = np.uint8(sure_fg)
unknown = cv2.subtract(sure_bg, sure_fg)# 標記標簽
_, markers = cv2.connectedComponents(sure_fg)# 增加1以確保背景不是0,而是1
markers = markers + 1# 標記未知區域為0
markers[unknown == 255] = 0# 應用分水嶺
cv2.watershed(image, markers)
image[markers == -1] = [255, 255, 255]# 遍歷所有的標記
for marker in np.unique(markers):if marker == 0 or marker == -1:# 忽略背景和邊界continue# 創建一個掩碼,使得當前標記區域為白色,其他區域為黑色mask = np.zeros(gray.shape, dtype=np.uint8)mask[markers == marker] = 255# 應用掩碼到原始圖像segmented_image = cv2.bitwise_and(image, image, mask=mask)# 顯示提取的區域cv2.imshow(f'Segmented area {marker}', segmented_image)# 顯示結果
cv2.imshow('Segmented Image', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

Segmented Image
cv2.watershed 用于基于標記的圖像分割的函數,實現了一種變體的分水嶺算法。這個函數的關鍵功能是將圖像分割成多個區域,這些區域基于提供的標記來確定。

def watershed(image, markers)

  1. image: 輸入參數。這是一個8位的3通道圖像,即一般的彩色圖像。這個圖像是要應用分水嶺算法進行分割的圖像。

  2. markers: 輸入/輸出參數。這是一個32位單通道圖像,代表標記。它的大小應該與 image 相同。在輸入時,markers 圖像中應該有正值(>0)標記出預期分割區域的大致輪廓。每個區域由一個或多個連接組件表示,像素值為1、2、3等。函數處理后,markers 中的每個像素將被設置為其所屬“種子”組件的值,或在區域邊界處被設置為-1。

    • 正值(>0): 表示不同的對象或區域。
    • 零值(0): 表示這些像素的歸屬尚未確定,需要算法來定義。
    • 負值(-1): 在函數輸出中,這表示不同區域之間的邊界。

cv2.watershed 函數的目的是根據提供的標記,將圖像分割成不同的區域。這對于圖像分割、對象識別和計算機視覺應用特別有用。在實際應用中,通常需要先對圖像進行預處理(如邊緣檢測、閾值化等),然后生成合適的標記圖像,最后應用這個函數進行分割。

1.3 GrabCut法

1.3.1 GrabCut法原理

GrabCut是一種基于圖論的圖像分割方法,使用用戶定義的前景和背景區域來初始化分割。算法通過迭代方式優化每個像素屬于前景或背景的概率。

1.3.2 GrabCut法實現步驟

  1. 用戶定義前景和背景區域。
  2. 算法初始化并迭代更新每個像素的標簽(前景或背景)。
  3. 使用GMM(高斯混合模型)對顏色分布建模。
  4. 利用圖割算法優化像素標簽。

1.3.3 代碼實現

import cv2
import numpy as np# 讀取圖像
image = cv2.imread('tulips.jpg')# 定義前景和背景模型
mask = np.zeros(image.shape[:2], np.uint8)
bgdModel = np.zeros((1, 65), np.float64)
fgdModel = np.zeros((1, 65), np.float64)# 定義矩形(用戶定義的前景區域)
rect = (100, 50, 200, 300)# 應用GrabCut
cv2.grabCut(image, mask, rect, bgdModel, fgdModel, 1, cv2.GC_INIT_WITH_RECT)# 提取前景和可能的前景區域
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
image = image * mask2[:, :, np.newaxis]# 顯示結果
cv2.imshow('GrabCut Image', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

GrabCut
cv2.grabCut 實現了 GrabCut 算法,這是一種用于圖像分割的迭代算法。GrabCut 算法可以有效地從圖像中分離前景(目標對象)和背景。

def grabCut(img, mask, rect, bgdModel, fgdModel, iterCount, mode=None)

  1. img: 輸入參數。這是一個8位的3通道圖像,即一般的彩色圖像。這個圖像是要應用 GrabCut 算法的對象。

  2. mask: 輸入/輸出參數。這是一個8位單通道的掩碼圖像。掩碼的元素可以是 GrabCutClasses 中的一個,表示像素的不同分類(如明確的背景、可能的背景、明確的前景、可能的前景)。當 mode 設置為 GC_INIT_WITH_RECT 時,函數會初始化這個掩碼。

  3. rect: 輸入參數,表示包含分割對象的感興趣區域(ROI)。當 mode == GC_INIT_WITH_RECT 時使用此參數。ROI 外的像素被標記為“明確的背景”。

  4. bgdModel: 輸入/輸出參數。這是用于背景模型的臨時數組。處理同一圖像時不應修改它。

  5. fgdModel: 輸入/輸出參數。這是用于前景模型的臨時數組。處理同一圖像時不應修改它。

  6. iterCount: 輸入參數,表示算法應該執行的迭代次數。

  7. mode: 輸入參數,操作模式,可以是 GrabCutModes 中的一個。常見模式包括 GC_INIT_WITH_RECT(使用矩形初始化)和 GC_INIT_WITH_MASK(使用掩碼初始化)。

cv2.grabCut 函數的主要用途是通過迭代方式將圖像中的目標對象與背景分離。這在圖像編輯、計算機視覺和對象識別等領域非常有用。函數的實現方式是先用一個矩形粗略地標記出感興趣的對象,然后算法迭代地改進前景和背景的分割。

1.4 Mean-Shift法

1.4.1 Mean-Shift法原理

Mean-Shift算法是一種基于特征空間分析的非參數密度估計技術。在圖像分割的上下文中,它通常用于基于顏色的聚類。

1.4.2 Mean-Shift法實現步驟

  1. 在特征空間(例如顏色空間)中選擇一個窗口。
  2. 計算窗口內所有點的均值。
  3. 移動窗口到均值位置。
  4. 重復步驟2和3,直到收斂。

1.4.3 代碼實現

import cv2# 讀取圖像
image = cv2.imread('tulips.jpg')# 轉換為灰度圖
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 應用Canny邊緣檢測
edges = cv2.Canny(gray, 50, 150)# Mean-Shift 參數
spatial_radius = 20  # 空間窗口大小
color_radius = 40    # 顏色窗口大小
max_pyramid_level = 2 # 金字塔層數# 應用Mean-Shift算法
result = cv2.pyrMeanShiftFiltering(image, spatial_radius, color_radius, max_pyramid_level)
# 轉換為灰度圖
gray = cv2.cvtColor(result, cv2.COLOR_BGR2GRAY)
# 應用Canny邊緣檢測
result_edges = cv2.Canny(gray, 50, 150)# 顯示結果
img_edges = cv2.merge([edges,edges,edges])
img_result_edges = cv2.merge([result_edges,result_edges,result_edges])
cv2.imshow('Mean-Shift Segmentation', cv2.vconcat([cv2.hconcat([image, img_edges]),cv2.hconcat([result,img_result_edges])
]))
cv2.waitKey(0)
cv2.destroyAllWindows()

Mean-Shift Segmentation
cv2.pyrMeanShiftFiltering 用于執行圖像分割的 Mean-Shift 算法的函數。這個函數主要用于平滑圖像的顏色梯度,同時保留邊緣信息,從而對圖像進行“平面化”處理。以下是對 cv2.pyrMeanShiftFiltering 函數的參數和功能的簡要介紹:

def pyrMeanShiftFiltering(src, sp, sr, dst=None, maxLevel=None, termcrit=None)

  1. src: 輸入參數,源圖像。這是一個8位的3通道圖像,即一般的彩色圖像。

  2. sp: 輸入參數,空間窗口半徑。這個參數決定了像素鄰域的大小。在此鄰域內進行Mean-Shift迭代。

  3. sr: 輸入參數,顏色窗口半徑。這個參數決定了顏色空間中像素鄰域的大小,用于在顏色空間內聚類。

  4. dst: 輸出參數,目標圖像。這是處理后的圖像,格式和大小與源圖像相同。

  5. maxLevel: 可選輸入參數,金字塔的最大層級。當這個值大于0時,算法首先在金字塔的最小層上執行,然后結果被傳播到更大的層上。

  6. termcrit: 可選輸入參數,終止條件。它決定了Mean-Shift迭代何時停止。

cv2.pyrMeanShiftFiltering 函數的主要功能是對圖像進行分割和平滑處理,同時保留邊緣。在空間和顏色空間中,函數對每個像素進行迭代,直到滿足終止條件。這個過程可以幫助去除圖像的細節和噪聲,同時保留主要的結構信息。這種方法在圖像分割和對象識別等應用中非常有用。在實際使用時,spsr 參數需要根據具體的應用場景和圖像內容進行調整。

二、圖像修復

在圖像處理領域,圖像修復是一項至關重要的技術,它涉及修復圖像中的損壞部分或去除不需要的對象。

2.1 圖像修復原理

圖像修復 (Inpainting)是一種用于修復圖像中損壞區域的技術。它通過分析周圍的像素來重建缺失或損壞的部分。OpenCV提供了兩種主要的Inpainting技術:Telea方法和Navier-Stokes方法。

2.1.1 Telea方法

Telea方法是一種基于快速行進算法的圖像修復技術。這種方法的核心思想是從損壞區域的邊緣開始,逐步向內部填充,直到整個區域被修復完畢。

原理
Telea方法的關鍵在于它如何選擇用于填充缺失區域的像素值。它考慮到了邊緣周圍像素的信息,并基于這些信息來估計缺失像素的最佳值。具體而言,該方法依賴于周圍像素的幾何距離和光強差異來計算修復值。

應用
Telea方法非常適合于修復小到中等大小的損壞區域。由于其基于邊緣信息進行填充,因此在修復裂縫或小孔等缺陷時表現尤為出色。

2.1.2 Navier-Stokes方法

Navier-Stokes方法是另一種流行的圖像修復技術。它基于流體動力學中的Navier-Stokes方程,適用于重建更大區域的圖像。

原理
這種方法將圖像修復問題視為一個流體動力學問題,其中圖像的每個像素都被視為流體粒子。它利用Navier-Stokes方程來模擬流體粒子的運動,從而估算缺失區域的像素值。

應用
Navier-Stokes方法特別適用于大面積損壞的修復,例如修復破損的古老照片或藝術作品中的大片缺失部分。該方法能夠有效地重建圖像的結構和紋理信息,使修復后的區域與周圍環境融合得更自然。

2.1.3 代碼實現

import cv2
import numpy as npdef inpaint_image(image, mask, inpaint_radius=3):restored_telea = cv2.inpaint(image, mask, inpaint_radius, cv2.INPAINT_TELEA)restored_ns = cv2.inpaint(image, mask, inpaint_radius, cv2.INPAINT_NS)return restored_telea, restored_ns# 加載圖像
image = cv2.imread('tulips.jpg')# 創建第一個掩模,用于模擬損壞的區域
mask1 = np.zeros(image.shape[:2], np.uint8)
mask1[40:60, 50:550] = 255  # 水平損壞區域
mask1[60:260, 300:320] = 255  # 垂直損壞區域
mask1[200:220, 100:300] = 255  # 水平損壞區域# 創建第二個掩模,用于模擬損壞的區域
mask2 = np.zeros(image.shape[:2], np.uint8)
cv2.circle(mask2, (395, 215), 80, 255, -1)  # 圓形損壞區域# 應用掩模,模擬損壞
damaged_image1 = image.copy()
damaged_image1[mask1 == 255] = [0, 0, 0]
damaged_image2 = image.copy()
damaged_image2[mask2 == 255] = [0, 0, 0]# 使用封裝的函數進行修復
restored_telea1, restored_ns1 = inpaint_image(damaged_image1, mask1)
restored_telea2, restored_ns2 = inpaint_image(damaged_image2, mask2)# 顯示結果
horizontal_stack1 = np.hstack((damaged_image1, restored_telea1, restored_ns1))
horizontal_stack2 = np.hstack((damaged_image2, restored_telea2, restored_ns2))
vertical_stack = np.vstack((horizontal_stack1, horizontal_stack2))
cv2.imshow('Restored Image Telea and Navier-Stokes', vertical_stack)
cv2.waitKey(0)
cv2.destroyAllWindows()

Restored Image Telea and Navier-Stokes
cv2.inpaint 用于修復圖像中的選定區域的函數。它基于圖像的鄰域信息來重建圖像的損壞或不希望的部分。這個函數特別適合用于去除掃描照片中的灰塵和劃痕,或從靜態圖像或視頻中去除不需要的對象。

def inpaint(src, inpaintMask, inpaintRadius, flags, dst=None)

  1. src: 輸入參數,源圖像。這應該是一個8位、16位無符號或32位浮點的單通道或三通道圖像。

  2. inpaintMask: 輸入參數,修復掩模。這是一個8位單通道圖像,非零像素指示需要修復的區域。

  3. inpaintRadius: 輸入參數,圓形鄰域的半徑。每個待修復點考慮的鄰域大小由此半徑決定。

  4. flags: 輸入參數,修復方法。可以是以下兩種之一:

    • INPAINT_NS: 基于 Navier-Stokes 的方法。
    • INPAINT_TELEA: Alexandru Telea 提出的方法。
  5. dst: 輸出參數,與源圖像大小和類型相同的輸出圖像。

cv2.inpaint 函數通過考慮待修復區域邊界附近的像素來重建選定的圖像區域。該方法可用于修復小的圖像區域,例如去除圖像中的小斑點或遮擋物。它通過估算損壞區域周圍的顏色和強度分布,以合理的方式填充這些區域,從而達到修復的效果。

在實際應用中,需要根據具體問題選擇合適的修復半徑和方法。例如,較小的半徑適用于小面積的修復,而較大的半徑可能更適合廣泛區域的修復。同樣,兩種不同的方法(INPAINT_NS 和 INPAINT_TELEA)在不同類型的圖像和損壞情況下可能會有不同的效果。

2.2 修補算法

2.2.1 修補算法原理

修補(Patching)算法通過選取圖像中未損壞的區域并用其覆蓋損壞部分來進行修復。這種方法對于去除圖像中的小對象或缺陷特別有效。

2.2.2 修補算法實現步驟

  1. 選擇一個圖像的未損壞區域作為補丁。
  2. 選擇需要修復的區域。
  3. 將補丁應用到損壞的區域。

2.2.3 OpenCV代碼實現

2.2.3.1 方形補丁修補
import cv2
import numpy as np# 加載圖像
image = cv2.imread('tulips.jpg')# 創建掩模,用于模擬損壞的區域
mask2 = np.zeros(image.shape[:2], np.uint8)
cv2.circle(mask2, (395, 215), 80, 255, -1)  # 圓形損壞區域# 應用掩模,模擬損壞
damaged_image = image.copy()
damaged_image[mask2 == 255] = [0, 0, 0]# 選擇一個補丁區域
# 注意:這里的坐標(x1, y1, x2, y2)需要根據您的圖像進行調整
x1, y1, x2, y2 = 20, 20, 140, 150  # 補丁區域的坐標
patch = image[y1:y2, x1:x2]# 確定損壞區域的坐標
# 這里我們使用與圓形損壞區域相同的坐標
dx1, dy1, dx2, dy2 = 395 - 80, 215 - 80, 395 + 80, 215 + 80# 確保補丁和損壞區域的大小相同
patch_resized = cv2.resize(patch, (dx2 - dx1, dy2 - dy1))# 應用補丁
restored_image = damaged_image.copy()
restored_image[dy1:dy2, dx1:dx2] = patch_resized# 顯示修復后的圖像
cv2.imshow('Restored Image', cv2.hconcat([image, damaged_image,restored_image]))
cv2.waitKey(0)
cv2.destroyAllWindows()

Restored Image

2.2.3.2 圓形補丁修補
import cv2
import numpy as np# 加載圖像
image = cv2.imread('tulips.jpg')# 創建掩模,用于模擬損壞的區域
mask2 = np.zeros(image.shape[:2], np.uint8)
cv2.circle(mask2, (395, 215), 80, 255, -1)  # 圓形損壞區域# 應用掩模,模擬損壞
damaged_image = image.copy()
damaged_image[mask2 == 255] = [0, 0, 0]# 選擇一個圓形補丁區域
px, py, radius = 78, 80, 70  # 原始補丁的半徑
patch_mask = np.zeros(image.shape[:2], np.uint8)
cv2.circle(patch_mask, (px, py), radius, 255, -1)# 創建原始補丁圖像
original_patch = np.zeros_like(image)
original_patch[patch_mask == 255] = image[patch_mask == 255]# 放大補丁到新半徑
new_radius = 80
scale_factor = new_radius / radius
resized_patch = cv2.resize(original_patch, (0, 0), fx=scale_factor, fy=scale_factor)# 重新創建圓形掩模以裁剪放大的補丁
resized_mask = np.zeros(resized_patch.shape[:2], np.uint8)
cv2.circle(resized_mask, (int(px*scale_factor), int(py*scale_factor)), new_radius, 255, -1)
final_patch = np.zeros_like(resized_patch)
final_patch[resized_mask == 255] = resized_patch[resized_mask == 255]restored_image = damaged_image.copy()
# 應用放大的圓形補丁
for i in range(-new_radius, new_radius):for j in range(-new_radius, new_radius):if i**2 + j**2 <= new_radius**2:restored_image[215 + i, 395 + j] = final_patch[int(py * scale_factor) + i, int(px * scale_factor) + j]# 顯示修復后的圖像
cv2.imshow('Restored Image', cv2.hconcat([image, damaged_image,restored_image]))
cv2.waitKey(0)
cv2.destroyAllWindows()

Restored Image


總結

在本篇博客中,我們探討了OpenCV中幾種常用的圖像分割方法:漫水填充法、分水嶺法、GrabCut法和Mean-Shift法,以及圖像修復技術:Telea方法和Navier-Stokes方法,還有修補算法。每種方法都有其獨特的原理和適用場景。漫水填充法和分水嶺法適用于基于區域的分割,GrabCut法適合交互式前景提取,而Mean-Shift法適用于基于密度的聚類分割。在圖像修復方面,Telea方法和Navier-Stokes方法提供了強大的工具,用于修復圖像中的損壞區域。

通過本篇博客,我們能夠獲得對OpenCV圖像分割和修復技術的基本理解,并能夠開始在自己的項目中應用這些技術。圖像處理是一個不斷發展的領域,隨著技術的進步,將有更多的方法和技術被開發出來。因此,持續學習和實踐對于保持在該領域的領先地位至關重要。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/165379.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/165379.shtml
英文地址,請注明出處:http://en.pswp.cn/news/165379.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

論文閱讀 (106):Decoupling maxlogit for out-of-distribution detection (2023 CVPR)

文章目錄 1 概述1.1 要點1.2 代碼1.3 引用 2 預備知識3 方法3.1 MaxLogit3.2 改進MaxCosine和MaxNorm3.3 DML 1 概述 1.1 要點 題目&#xff1a;解耦最大logit分布外檢測 (Decoupling maxlogit for out-of-distribution detection) 方法&#xff1a; 提出了一種心機基于log…

多級緩存快速上手

哈嘍~大家好&#xff0c;這篇來看看多級緩存。 &#x1f947;個人主頁&#xff1a;個人主頁????? &#x1f948; 系列專欄&#xff1a;【微服務】 &#x1f949;與這篇相關的文章&#xff1a; JAVA進程和線程JAVA進程和線程-CSDN博客Http…

不做機器視覺工程師,轉行,轉崗的建議與想法

正所謂外行看熱鬧&#xff0c;內行看門道。提前咨詢前輩們&#xff0c;多問問&#xff0c;多看看。要做就做&#xff0c;一定要提前做好防范。 無論你是要轉行或者是轉崗&#xff0c;看你有沒有本錢和試錯成本 有些人&#xff0c;家庭好&#xff0c;可以一直去試錯和從頭再來。…

無線WiFi安全滲透與攻防(國外篇):使用 Aircrack-ng 破解 WEP 密碼

使用 Aircrack-ng 破解 WEP 密碼 使用 Aircrack-ng 破解 WEP 密碼一. 用 Aircrack-ng 破解 WEP 密碼 - 背景知識網卡與網卡芯片WEP 加密協議WEP 所使用的身份認證協議二. 使用 Aircrack-ng 破解 WEP 密碼 - 破解原理破解機理三. 使用 Aircrack-ng 破解 WEP 密碼 - aircrack-ng …

學習.NET驗證模塊FluentValidation的基本用法(續1:其它常見用法)

FluentValidation模塊支持鏈式驗證方法調用&#xff0c;也就是說&#xff0c;除了 RuleFor(r > r.UserName).NotEmpty()調用方式之外&#xff0c;還可以將對單個屬性的多種驗證函數以鏈式調用方式串接起來&#xff0c;比如UserName屬性不能為空&#xff0c;長度在5~10之間&a…

__attribute__((constructor))用法解析

__attribute__((constructor))是GCC和兼容的編譯器中的一個特性&#xff0c;用于指示編譯器將一個函數標記為在程序啟動時自動執行的初始化函數。 同樣的還有__attribute__((destructor))在main()函數后調用。 當你在一個函數聲明或定義前加上__attribute__((constructor))屬…

淺談 Guava 中的 ImmutableMap.of 方法的坑

作者&#xff1a;明明如月學長&#xff0c; CSDN 博客專家&#xff0c;大廠高級 Java 工程師&#xff0c;《性能優化方法論》作者、《解鎖大廠思維&#xff1a;剖析《阿里巴巴Java開發手冊》》、《再學經典&#xff1a;《EffectiveJava》獨家解析》專欄作者。 熱門文章推薦&…

vue項目下.env.development環境變量配置文件

.env.development 文件是一個用于開發環境配置的文件。在許多應用程序中&#xff0c;開發環境和生產環境具有不同的配置需求。.env.development 文件允許你在開發環境中定義特定的環境變量和配置選項。 一般來說&#xff0c;.env.development 文件用于存儲開發環境相關的配置信…

國自然項目基金撰寫的隱藏技巧、范例分析及提交前的自我審查

目錄 一、基金項目申請要求、重點及項目介紹 二、基金的撰寫技巧 三、基金撰寫的隱藏技巧 四、范例分析及提交前的自我審查 更多應用 基金項目申請需要進行跨學科的技術融合&#xff0c;申請人需要與不同領域結合&#xff0c;形成多學科交叉的研究。基金項目申請在新時期更…

由紅黑樹引出的HashMap擴容機制的思考

紅黑樹是什么&#xff1f; 三大特點&#xff1a; 根節點是黑色&#xff0c;葉節點是不存儲數據的黑色空節點 任何相鄰的兩個節點不能同時為紅色 任意節點到其可到達的節點間包含相同數量的黑色節點 聯想&#xff1a;Java HashMap底層紅黑樹原理 HashMap基于哈希表Map接口實…

快速掌握Pyqt5的三種主窗口

PyQt5是一個強大的跨平臺GUI框架&#xff0c;它提供了多種不同類型的主窗口類&#xff0c;以滿足不同的應用需求。下面是PyQt5中最常見的幾種主窗口類型及其創建方式的簡介&#xff1a; 1. QMainWindow QMainWindow是用于創建具有菜單欄、工具欄、狀態欄和中心窗口部件&#…

內存池 示例一

內存池是一種管理內存分配和釋放的技術&#xff0c;用于優化內存的使用效率。它通過預先分配一塊內存區域&#xff0c;并將其劃分為多個較小的塊&#xff08;內存塊池&#xff09;&#xff0c;然后按需分配這些內存塊來減少內存碎片化和頻繁的系統調用。這些內存塊可以是相同大…

Centos7.9配置nfs共享及rsync同步

客戶需求對oracle數據庫做一個跨機房的備份&#xff0c;原環境已做rman備份和每天expdp全庫導出&#xff0c;遠端只有虛擬化環境&#xff0c;可提供一個虛擬機&#xff0c;2個機房間網絡互通。 首先配置nfs服務端 查看操作系統版本 [rootnas199 ~]# more /etc/redhat-relea…

Python面經【1】

一、協程的相關概念 協程&#xff08;又稱微線程&#xff09;運行在線程之上&#xff0c;更加輕量級&#xff0c;協程并沒有增加線程總數&#xff0c;只是在線程的基礎上通過分時復用的方式運行多個協程&#xff0c;大大提高工程效率。 協程的特點&#xff1a; 輕量級&#…

WordPress站點屏蔽過濾垃圾評論教程(Akismet反垃圾評論插件)

前段時間我的WordPress站點經常收到垃圾評論的轟炸&#xff0c;嚴重時一天會收到幾十條垃圾評論。我這個小破站一沒啥流量&#xff0c;二又不盈利&#xff0c;實在是不太理解為啥有人要這么執著地浪費資源在上面。 Akismet反垃圾評論插件 其實用了 Akismet 反垃圾評論插件后&a…

快速掌握Pyqt5的6種按鈕

在PyQt5中&#xff0c;按鈕是構建用戶界面的基本元素之一&#xff0c;用于執行命令、啟動功能或觸發事件。PyQt5提供了多種類型的按鈕&#xff0c;每種都適用于不同的場景和需求。 1. QPushButton QPushButton 是最常用的按鈕類型&#xff0c;適用于大多數情況&#xff0c;如…

ARCore:在Android上構建令人驚嘆的增強現實體驗

ARCore&#xff1a;在Android上構建令人驚嘆的增強現實體驗 一、 AR 介紹1.1 AR技術簡介1.2 AR技術原理1.3 AR技術應用領域 二、Google的增強現實平臺ARCore2.1 ARCore簡介2.2 ARCore API介紹2.3 ARCore API使用示例 三、總結 一、 AR 介紹 增強現實 Augmented Reality&#x…

【算法-字符串2】替換空格 + 反轉單詞

今天&#xff0c;帶來字符串相關算法的講解。文中不足錯漏之處望請斧正&#xff01; 理論基礎點這里 1. 替換空格 題目描述&#xff1a;請實現一個函數&#xff0c;把字符串 s 中的每個空格替換成"%20"。 來源&#xff1a;力扣&#xff08;LeetCode&#xff09; 難…

Lettuce使用詳解

簡介特點連接池連接池特點連接池管理連接池優勢連接池配置參數 監控常用監控工具通過JMX監控通過Prometheus監控 代碼示例拓展springboot中通過jmx上報到Prometheus代碼示例更多Redis相關內容 簡介 Lettuce 是一個高級的、線程安全的 Redis 客戶端&#xff0c;用于與 Redis 數…

深度學習基礎概念

1. 神經網絡基礎 神經元&#xff08;Neuron&#xff09;&#xff1a; 了解神經網絡的基本組成單元。激活函數&#xff08;Activation Function&#xff09;&#xff1a; 學習常見的激活函數&#xff0c;如Sigmoid、ReLU等&#xff0c;以及它們在神經網絡中的作用。前饋神經網絡…