基於 opencv 的圖像處理入門教程

前言

雖然計算機視覺領域目前基本是以深度學習算法爲主,但實際上不少時候對圖片的不少處理方法,並不須要採用深度學習的網絡模型,採用目前成熟的圖像處理庫便可實現,好比 OpenCV 和 PIL ,對圖片進行簡單的調整大小、裁剪、旋轉,或者是對圖片的模糊操做。html

因此本文主要是介紹用 OpenCV 實現一些基本的圖像處理操做,本文的目錄以下所示:python

  1. 安裝
  2. 旋轉圖片
  3. 裁剪圖片
  4. 調整圖片大小
  5. 調整圖片對比度
  6. 模糊圖片
    • 高斯模糊
    • 中值模糊
  7. 邊緣檢測
  8. 轉爲灰度圖
  9. 形心檢測
  10. 對彩色圖片採用蒙版(mask)
  11. 提取圖片的文字(OCR)
  12. 檢測和修正歪曲的文字
  13. 顏色檢測
  14. 去噪
  15. 檢測圖片的輪廓
  16. 移除圖片的背景

原文地址:git

https://likegeeks.com/python-image-processing/github

代碼和樣例圖片的地址:算法

https://github.com/ccc013/CodesNotes/tree/master/opencv_noteswindows

https://github.com/ccc013/CodesNotes/blob/master/opencv_notes/opencv_image_process_tutorial.ipynb數組


1. 安裝

OpenCV 的安裝仍是比較簡單的,直接用 pip 命令在命令行安裝便可,輸入如下命令:網絡

pip install opencv-python

驗證是否安裝成功,能夠運行 python 命令,而後分別輸入如下命令:函數

import cv2

運行成功,沒有報錯,即安裝成功。學習

2. 旋轉圖片

首先,仍是須要導入 cv2 模塊:

import cv2

而後第一件事情就是讀取圖片,調用imread 函數便可,輸入參數是圖片的路徑,以下代碼所示:

# 讀取圖片
img = cv2.imread('example.jpg')
print(f'type: {type(img)}')
plt.axis('off')
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))

而後打印讀取的圖片類型,能夠知道是一個numpy 的多維數組,即矩陣的形式。

上述代碼運行結果以下:

下面的全部功能實現,我都是在 jupyter notebook 上實現的,因此展現圖片部分和原文有所不一樣,原文展現圖片代碼是採用:

cv2.imshow('original image', img)
cv2.waitKey(0)

而在 jupyter 中,須要先導入下面的庫:

import matplotlib.pyplot as plt
%matplotlib inline

而後直接調用 plt.imshow() 函數,不過 opencv 都須要作一個轉換過程,即:

plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))

讀取好圖片後,接下來就是實現旋轉圖片,這裏分爲如下三個步驟:

  1. 獲取圖片的寬和高
  2. 調用函數cv2.getRotationMatrix2D() 獲得旋轉矩陣
  3. 經過 wrapAffine 實現旋轉

實現的代碼以下所示:

# 獲取圖片的寬、高
height, width = img.shape[:2]
print(height, width)
rotationMatrix = cv2.getRotationMatrix2D((width/2, height/2), 45, .5)
rotationImage = cv2.warpAffine(img, rotationMatrix, (width, height))
print(f'rotation image shape:{rotationImage.shape}')
plt.imshow(cv2.cvtColor(rotationImage, cv2.COLOR_BGR2RGB))

結果以下所示:

3. 裁剪圖片

裁剪圖片的步驟以下:

  1. 讀取圖片,並獲取圖片的寬和高;
  2. 肯定裁剪後圖片的寬和高;
  3. 開始裁剪操做

實現代碼以下所示:

img = cv2.imread('example.jpg')
height, width = img.shape[:2]
print(f'origin image shape:{img.shape}')
# 設置裁剪後圖片的大小
start_row = int(height * 0.15)
start_col = int(width * 0.15)
end_row = int(height * 0.85)
end_col = int(width * 0.85)
# 裁剪圖片
cropped_image = img[start_row:end_row, start_col:end_col]
print(f'crop image shape:{cropped_image.shape}')
plt.axis('off')
plt.imshow(cv2.cvtColor(cropped_image, cv2.COLOR_BGR2RGB))

效果以下圖所示:

4. 調整圖片大小

對圖片進行調整大小的操做,採用的是resize() 函數,這裏有兩種方式進行調整大小:

  1. 座標軸方式來指定縮放比例,即fx, fy 參數;
  2. 直接給出調整後圖片的大小。

第一種方式的實現代碼:

img = cv2.imread('example.jpg')
height, width = img.shape[:2]
print(f'origin image shape:{img.shape}')
# 1
new_img = cv2.resize(img, (0, 0), fx=0.75, fy=0.75)
print(f'new img shape:{new_img.shape}')
plt.axis('off')
plt.imshow(cv2.cvtColor(new_img, cv2.COLOR_BGR2RGB))

實現效果:

第二種方法的實現代碼:

# 2
new_img = cv2.resize(img, (800, 800))
print(f'new img shape:{new_img.shape}')
plt.axis('off')
plt.imshow(cv2.cvtColor(new_img, cv2.COLOR_BGR2RGB))

實現結果以下所示:

5. 調整圖片對比度

在 Python 的 OpenCV 模塊中並無特定的實現調整圖片對比度的函數,但官方文檔給出實現調整圖片亮度和對比度的公式,以下所示:

new_img = a*original_img + b

官方文檔地址:

https://docs.opencv.org/master/d3/dc1/tutorial_basic_linear_transform.html

這裏公式中的 a 就是 $\alpha$, 表示圖片的對比度,

  • 若是它大於 1,就是高對比度;
  • 若是在 0-1 之間,那就是低對比度;
  • 等於 1,表示沒有任何變化

b 是 $\beta$ ,數值範圍是 -127 到 127;

要實現上述公式,能夠採用 addWeighted() 方法,它輸出的圖片是一個 24 位的 0-255 範圍的彩色圖片。

其語法以下所示:

cv2.addWeighted(source_img1, alpha1, source_img2, alpha2, beta)

這個方法是接收兩張輸入的圖片,而後根據 alpha1alpha2 來將兩種圖片進行融合。

若是隻是想調整圖片的對比度,那麼能夠將第二個圖片經過 Numpy 設置爲 0。

因此,實現的代碼以下所示:

import numpy as np
img = cv2.imread('example.jpg')
# 高對比度
hight_contrast_img = cv2.addWeighted(img, 2.5, np.zeros(img.shape, img.dtype), 0, 0)
# 低對比度
low_contrast_img = cv2.addWeighted(img, 0.5, np.zeros(img.shape, img.dtype), 0, 0)
plt.figure(figsize=(32, 16))
plt.subplot(3, 1, 1)
plt.title('origin image')
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.subplot(3, 1, 2)
plt.title('hight contrast image')
plt.imshow(cv2.cvtColor(hight_contrast_img, cv2.COLOR_BGR2RGB))
plt.subplot(3, 1, 3)
plt.title('low contrast image')
plt.imshow(cv2.cvtColor(low_contrast_img, cv2.COLOR_BGR2RGB))

實現效果以下所示:

6. 模糊圖片

高斯模糊

高斯模糊採用的是 GaussianBlur() 方法,採用高斯核,而且核的寬和高必須是正數,且是奇數。

高斯濾波主要用於消除高斯噪聲,能夠保留更多的圖像細節,常常被稱爲最有用的濾波器。

實現的代碼以下所示:

img = cv2.imread('example.jpg')
blur_img = cv2.GaussianBlur(img, (7, 7), 3)
plt.figure(figsize=(32, 32))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(blur_img, cv2.COLOR_BGR2RGB))

實現效果:

中值模糊

對於中值模糊,就是用區域內的中值來代替本像素值,所以孤立的斑點,好比 0 或者 255 的數值很容易消除掉。

因此中值模糊主要用於消除椒鹽噪聲和斑點噪聲。

實現代碼:

img = cv2.imread('example.jpg')
blur_img = cv2.medianBlur(img, 5)
plt.figure(figsize=(32, 32))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(blur_img, cv2.COLOR_BGR2RGB))

實現效果以下所示:

7. 邊緣檢測

邊緣檢測主要是經過Canny() 方法,它實現了 Canny 邊緣檢測器,這也是目前最優的邊緣檢測器。

Canny() 方法的語法以下:

cv2.Canny(image, minVal, maxVal)

其中 minValmaxVal 分別表示梯度強度值的最小值和最大值。

實現代碼以下:

img = cv2.imread('example.jpg')
edge_img = cv2.Canny(img, 100, 200)
plt.figure(figsize=(32, 32))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(edge_img, cv2.COLOR_BGR2RGB))

實現結果:

8. 轉爲灰度圖

最簡單的將圖片轉爲灰度圖的方法,就是讀取的時候,代碼以下所示:

img = cv2.imread("example.jpg", 0)

而另外一種方法就是用 BGR2GRAY ,實現代碼:

img = cv2.imread('example.jpg')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

plt.figure(figsize=(32, 32))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(gray_img, cv2.COLOR_BGR2RGB))

實現效果:

9. 形心檢測

檢測一張圖片的形心位置,實現步驟以下所示:

  1. 讀取圖片,並轉爲灰度圖;
  2. 經過moments() 方法計算圖片的 moments
  3. 接着利用第二步的結果來計算形心的 x,y 座標
  4. 最後能夠繪圖展現檢測的結果。

本例使用的圖片以下:

實現代碼:

gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
moment = cv2.moments(gray_img)
X = int(moment ["m10"] / moment["m00"])
Y = int(moment ["m01"] / moment["m00"])
cv2.circle(img, (X, Y), 50, (205, 114, 101), 1)

plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))

實現的效果:

10.對彩色圖片採用蒙版(mask)

圖像蒙版就是將一張圖片做爲另外一張圖片的蒙版,或者是修改圖片中的像素值。

本例中將採用HoughCircles() 方法來應用蒙版,這個方法能夠檢測圖片中的圓,而後對這些圓應用蒙版。

本例採用的圖片爲:

實現代碼:

img1 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
circles = cv2.HoughCircles(gray_img, cv2.HOUGH_GRADIENT, 1, 20, param1=50, param2=50, minRadius=0, maxRadius=0)
circles = np.uint16(np.around(circles))

masking=np.full((img1.shape[0], img1.shape[1]),0,dtype=np.uint8)
for j in circles[0, :]:
    cv2.circle(masking, (j[0], j[1]), j[2], (255, 255, 255), -1)
final_img = cv2.bitwise_or(img1, img1, mask=masking)
plt.imshow(cv2.cvtColor(final_img, cv2.COLOR_BGR2RGB))

實現效果:

11.提取圖片的文字(OCR)

實現提取圖片的文字是經過安裝使用谷歌的 Tesseract-OCR,首先須要從下面這個網址中下載:

https://digi.bib.uni-mannheim.de/tesseract/tesseract-ocr-setup-3.05.02-20180621.exe

接着再進行安裝:

pip install pytesseract

若是是 mac,安裝步驟能夠是這樣的:

brew install tesseract
pip install pytesseract

本例使用的圖片:

實現代碼以下所示:

import pytesseract

pytesseract.pytesseract.tesseract_cmd = '/usr/local/bin/tesseract'
img = cv2.imread('pytext.png')
pytesseract.image_to_string(img)

實現結果:

注意這裏須要設置 tesseract 的執行路徑,兩種方法,第一種是設置環境變量:

windows 版:https://blog.csdn.net/luanyongli/article/details/81385284

第二種是在代碼中進行指定,即代碼中pytesseract.pytesseract.tesseract_cmd = '/usr/local/bin/tesseract'

這裏我用的是 Mac,因此這個路徑能夠在命令行中輸入which tesseract 來找到。

12. 檢測和修正歪曲的文字

在本例中,使用的圖片以下:

首先仍是先讀取圖片,並轉換爲灰度圖:

接着採用 bitwise_not 方法將背景和文字顏色進行交換,變成白字黑底:

接着分別找到 x,y 座標中大於 0 值的像素值,並經過minAreaRect() 計算獲得歪曲的角度,接着就是計算要修正的角度,而後再經過以前旋轉圖片的方法來修正,實現代碼和結果以下:

完整的實現代碼:

import cv2
import numpy as np

img = cv2.imread('Skewed-text-image.png')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray_img = cv2.bitwise_not(gray_img)
coordinates = np.column_stack(np.where(gray_img > 0))
ang=cv2.minAreaRect(coordinates)[-1]

if ang<-45:
    angle=-(90+ang)
else:
    angle=-ang

height, width = img.shape[:2]
center_img = (width / 2, height / 2)

rotationMatrix = cv2.getRotationMatrix2D(center_img, angle, 1.0)
rotated_img = cv2.warpAffine(img, rotationMatrix, (width, height), borderMode = cv2.BORDER_REFLECT)
plt.imshow(cv2.cvtColor(rotated_img, cv2.COLOR_BGR2RGB))

13. 顏色檢測

在本次例子中實現檢測圖片中的綠色區域,使用的圖片:

首先是讀取圖片後,轉換到 HSV 空間:

接着須要經過 Numpy 設置綠色像素值的上下範圍區間:

lower_green = np.array([34, 177, 76])
upper_green = np.array([255, 255, 255])

接着經過 inRange() 方法來判斷輸入圖片中是否包含在設置後的綠色區間範圍內,若是有,那就表示檢測到綠色這種顏色的像素區域。

完整實現的代碼:

import cv2
import numpy as np

img = cv2.imread("pycolor.png")
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
plt.imshow(cv2.cvtColor(hsv_img, cv2.COLOR_BGR2RGB))

lower_green = np.array([34, 177, 76])
upper_green = np.array([255, 255, 255])

masking = cv2.inRange(hsv_img, lower_green, upper_green)
plt.imshow(cv2.cvtColor(masking, cv2.COLOR_BGR2RGB))

實現結果:

14. 去噪

OpenCV 中提供了下面 4 種圖像去噪的方法:

  1. fastNlMeansDenoising():從灰度圖中降噪;
  2. fastNlMeansDenoisingColored():從彩色圖片中降噪
  3. fastNlMeansDenoisingMulti():從灰度圖片幀(灰度視頻)中降噪;
  4. fastNlMeansDenoisingColoredMulti():從彩色圖片幀中降噪

本次例子會用第二種方法:fastNlMeansDenoisingColored()

實現的代碼以下所示:

import cv2

img = cv2.imread('example.jpg')
result = cv2.fastNlMeansDenoisingColored(img,None,20,10,7,21)

plt.figure(figsize=(32, 32))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB))

其中對於方法fastNlMeansDenoisingColored()的個參數分別是:

  • 輸入的原圖
  • 輸出圖片,不過這裏設置爲 None,咱們直接保存到 result 變量裏;
  • 濾波器強度
  • 和濾波器強度同樣,但針對的是彩色圖片的噪聲,通常設置爲 10;
  • 模板塊像素大小,必須是奇數,通常設置爲 7;
  • 計算給定像素均值的窗口大小

實現結果:

15. 檢測圖片的輪廓

輪廓是圖片中將連續的點鏈接在一塊兒的曲線,一般檢測輪廓的目的是爲了檢測物體。本例中使用的圖片以下:

檢測輪廓的步驟以下:

  1. 讀取圖片,並轉爲灰度圖;
  2. 經過threshold() 找到閾值,一般設置 127-255 的區間
  3. 採用 findContours() 進行檢測輪廓,具體使用方法能夠查看官方文檔:https://docs.opencv.org/3.4.2/d3/dc0/group__imgproc__shape.html#ga17ed9f5d79ae97bd4c7cf18403e1689a
  4. 最後是經過drawContours() 來繪製畫好的輪廓,而後展現出來

實現代碼:

import cv2

img = cv2.imread('opencv_contour_example.png')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
retval, thresh = cv2.threshold(gray_img, 127, 255, 0)
img_contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, img_contours, -1, (0, 255, 0))
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))

實現效果:

16. 移除圖片的背景

移除圖片背景的實現思路是這樣的:

  1. 檢測圖片主要物體的輪廓;
  2. 爲背景經過np.zeros 生成一個蒙版 mask;
  3. 採用 bitwise_and 運算符來結合檢測輪廓後的圖片和蒙版 mask

本次樣例使用的原圖:

實現代碼:

import cv2
import numpy as np

img = cv2.imread("opencv_bg.png")
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
img_contours = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2]
img_contours = sorted(img_contours, key=cv2.contourArea)

for i in img_contours:
    if cv2.contourArea(i) > 100:
        break
mask = np.zeros(img.shape[:2], np.uint8)
cv2.drawContours(mask, img_contours, -1, 255, -1)
new_img = cv2.bitwise_and(img, img, mask=mask)

plt.figure(figsize=(32, 32))
plt.subplot(1, 2, 1)
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.subplot(1, 2, 2)
plt.imshow(cv2.cvtColor(new_img, cv2.COLOR_BGR2RGB))

實現結果:


小結

本文是簡單介紹了基於 opencv 實現的一些圖像處理操做,從基礎的旋轉,裁剪,調整大小,到模糊圖片,邊緣檢測,修正歪曲文字,去噪,檢測輪廓等操做,都給出了基礎的實現代碼,若是須要更深刻了解,這裏推薦:

  1. opencv 官方文檔:https://docs.opencv.org/master/d9/df8/tutorial_root.html
  2. https://github.com/ex2tron/OpenCV-Python-Tutorial
  3. 圖像處理 100 問:https://github.com/gzr2017/ImageProcessing100Wen

最後,原文地址:

https://likegeeks.com/python-image-processing/

代碼和樣例圖片的地址:

https://github.com/ccc013/CodesNotes/tree/master/opencv_notes

https://github.com/ccc013/CodesNotes/blob/master/opencv_notes/opencv_image_process_tutorial.ipynb

歡迎關注個人公衆號--算法猿的成長

相關文章
相關標籤/搜索