文章目錄
-
- 1.在Ubuntu16.04系統上安裝OpenCV和imutils
- 2.檢視我們opencv項目結構
- 3.加載并顯示圖像
- 4.通路單個像素
- 5.提取感興趣區域(ROI)
- 6.調整圖像大小
- 7.旋轉圖像
- 8.平滑圖像
- 9.在圖像上繪圖
- 10.運作腳本
1.在Ubuntu16.04系統上安裝OpenCV和imutils
(1)opencv安裝在我之前的博文上介紹過可以翻閱;
(2)安裝imutils:
pip install imutils
如果是使用虛拟環境的話,記得進入虛拟環境後再安裝imutils
簡單介紹一下imutils:它是在opencv的基礎上對一些方法進行了封裝,使得一些圖像處理方法更友善易用
2.檢視我們opencv項目結構
假設我們将下載下傳到的源碼存放在“下載下傳”檔案夾下,執行以下指令:
cd 下載下傳
unzip opencv-tutorial.zip
cd opencv-tutorial
tree
opencv項目結構.png
第一個腳本opencv_tutorial_01.py将使用電影《侏羅紀公園》中的圖像(jp.png)進行基本的圖像處理操作。
第二個腳本opencv_tutorial_02.py将介紹如何使用這些圖像處理子產品來建立OpenCV應用程式,以計算Tetris圖像(tetris_blocks.png )中的對象數量。
3.加載并顯示圖像
首先在文本編輯器或IDE中打開opencv_tutorial_01.py:
#導入必要的軟體包
import imutils
import cv2
#加載并顯示圖像尺寸
#将圖像表示為包含h、w、d的多元numpy數組即變量"image"
#形狀參數包括行(height) x 列 (width) x 通道 (depth)
image = cv2.imread("jp.png")
(h, w, d) = image.shape
print("width={}, height={}, depth={}".format(w, h, d))
#在螢幕上顯示圖像,滑鼠要點選到圖像視窗
#按任意鍵繼續執行程式
cv2.imshow("Image", image)
cv2.waitKey(0)
深度是通道數——在我們的例子中是3,因為我們正在使用3個顔色通道:藍色,綠色和紅色(RGB)。
print輸出寬、高、深度:
width=600, height=322, depth=3
cv2.waitKey(0):等待按鍵,這一點很重要,否則我們的圖像顯示和消失的速度将比我們看到圖像還要快
4.通路單個像素
所有圖像都由像素組成,640 x 480圖像具有640列(寬度)和480行(高度),有640×480 = 307200個像素點
灰階圖像中的每個像素都有一個代表灰階的值,在OpenCV中,有256種灰階(從0到255)。是以,灰階圖像将具有與每個像素關聯的灰階值。
彩色圖像中的像素具有其他資訊,在學習圖像處理時很快就會熟悉幾種色彩空間。為簡單起見,我們僅考慮RGB顔色空間。
在OpenCV彩色圖像中,RGB(紅色,綠色,藍色)顔色空間中的每個像素都有一個3元組(B, G, R) ,注意,順序是BGR而不是RGB。
BGR 3元組中的每個值的範圍為[0, 255] 。OpenCV中RGB圖像中的每個像素有多少種顔色可能性?這很簡單:256×256×256 = 16777216
圖像坐标系規定是左上角為(0,0)
#通路位于x = 50(w),y = 100(h)的RGB像素
#OpenCV以BGR而不是RGB的順序存儲圖像
(B, G, R) = image[100, 50]
print("R={}, G={}, B={}".format(R, G, B))
前面已知圖檔尺寸為width=600, height=322, depth=3 。我們可以通過指定坐标來通路數組中的各個像素值,隻要它們在最大寬度和高度之内即可,圖像指定像素點的格式為:image[Y,X]。
在終端列印出該像素的RGB值:
R=41, G=49, B=37
5.提取感興趣區域(ROI)
提取“感興趣區域”(ROI)是圖像處理的一項重要技能。
舉例來說,您正在識别電影中的人臉。首先,您将運作人臉檢測算法以查找正在使用的所有幀中人臉的坐标。然後,您需要提取面部ROI,然後儲存它們或對其進行處理。
手動提取ROI通過數組切片來實作:
#從輸入圖像提取一個100*100的感興趣區,
#從x=320,y=60到x=420,y=160,并顯示圖像
roi = image[60:160, 320:420]
cv2.imshow("ROI", roi)
cv2.waitKey(0)
數組切片的格式為:image[startY:endY, startX:endX],注意前閉後開
6.調整圖像大小
調整圖像大小很重要,原因有很多。首先,我們可能需要調整大圖像的大小以适合螢幕。在較小的圖像上,圖像處理也更快,因為要處理的像素更少。在深度學習的情況下,我們經常忽略寬高比來調整圖像的大小,以使體積适合網絡,這要求圖像是正方形且具有一定尺寸。
#忽略寬高比,将原始圖像調整為200 x 200像素:
resized = cv2.resize(image, (200, 200))
cv2.imshow("Fixed Resizing", resized)
cv2.waitKey(0)
由于忽略了寬高比,得到的圖像已經失真。
假設要将600像素寬的圖像調整為300像素寬,同時保持寬高比。
#固定大小調整扭曲了寬高比,是以讓我們将寬度調整為300px,
#但根據寬高比得到height
r = 300.0 / w
dim = (300, int(h * r))
resized = cv2.resize(image, dim)
cv2.imshow("Aspect Ratio Resize", resized)
cv2.waitKey(0)
我們計算新寬度與舊寬度的比率(恰好是0.5)。
在此,我們指定新圖像的尺寸dim 。我們知道,我們希望有一個300像素寬的圖像,但我們必須乘以該比例計算新高度h。
将dim(圖像的尺寸)輸入到cv2.resize函數中,我們現在獲得了一個名為resized的新圖像,該圖像沒有失真。
但是,我們是否可以使調整大小時保持寬高比的過程變得更加容易?
使用imutils中的函數:imutils.resize
#手動計算寬高比可能很麻煩,
#是以讓我們使用#imutils庫來代替
resized = imutils.resize(image, width=300)
cv2.imshow("Imutils Resize", resized)
cv2.waitKey(0)
這樣保留了寬高比并調整圖像的大小隻需要需要提供圖像的width或height作為參數
7.旋轉圖像
# 首先計算圖像中心,"//"表示向下取整除
# 構造旋轉矩陣
# 最後應用warpAffine函數旋轉圖像
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, -45, 1.0)
rotated = cv2.warpAffine(image, M, (w, h))
cv2.imshow("OpenCV Rotation", rotated)
cv2.waitKey(0)
-45表示将圖像順時針旋轉45度。回憶一下中學關于機關圓的資訊,正角是逆時針方向,負角是順時針方向。
# 使用imutils執行相同的操作
rotated = imutils.rotate(image, -45)
cv2.imshow("Imutils Rotation", rotated)
cv2.waitKey(0)
但是以上的操作都使圖像被裁剪,運用imutils.rotate_bound函數使整個圖像保持可見。 :
rotated = imutils.rotate_bound(image, 45)
cv2.imshow("Imutils Bound Rotation", rotated)
cv2.waitKey(0)
8.平滑圖像
在許多圖像處理場合中,我們必須對圖像進行模糊處理以減少高頻噪聲,進而使我們的算法更容易檢測和了解圖像的實際内容,在OpenCV中,對圖像進行模糊處理非常容易,并且有多種方法可以完成圖像處理。
# 将具有11x11核心的高斯模糊應用于圖像以使其平滑,減少高頻噪聲
blurred = cv2.GaussianBlur(image, (11, 11), 0)
cv2.imshow("Blurred", blurred)
cv2.waitKey(0)
較大的核心将産生更模糊的圖像,較小的核心将建立較少的模糊圖像。
9.在圖像上繪圖
我們将在輸入圖像上繪制矩形,圓形和直線,我們還将在圖像上覆寫文本。
在繼續使用OpenCV在圖像上繪圖之前,請注意,在圖像上進行繪圖操作是直接執行的。是以,在每個代碼塊的開頭,我們制作原始圖像的副本,并将副本存儲為output 。然後,我們繼續繪制output的圖像,以免破壞原始圖像。
(1)在伊恩·馬爾科姆(Ian Malcolm)的臉上繪制一個矩形:
# 在男主臉上畫個矩形,線粗為2
output = image.copy()
cv2.rectangle(output, (320, 60), (420, 160), (0, 0, 255), 2)
cv2.imshow("Rectangle", output)
cv2.waitKey(0)
在OpenCV中繪制矩形比較簡單,使用預先計算的坐标,向cv2.rectangle函數提供了以下參數:
- img :要繪制的目标圖像output
- pt1 :起始像素坐标,在我們的例子中位于左上角,(320, 60)
- pt2 :結束像素坐标,右下角的像素位于(420, 160)
- color :BGR元組,紅色(0 , 0, 255)
- thickness :線粗(負值将形成一個實心矩形),,這裡為2
由于我們使用的是OpenCV的函數而不是NumPy的操作,是以我們可以按(x,y)的順序而不是(y,x)的順序提供坐标,因為我們沒有直接操作或通路NumPy數組為我們處理這些事情。
(2)在Ellie Sattler博士的臉前放置一個藍色實心圓:
# 畫一個實心藍色圓在x=300,y=150
output = image.copy()
cv2.circle(output, (300, 150), 20, (255, 0, 0), -1)
cv2.imshow("Circle", output)
cv2.waitKey(0)
要繪制圓,需要向cv2.circle提供以下參數 :
- img :圖像名稱
- center :圓的中心坐标,這裡是(300, 150)
- radius :圓半徑(以像素為機關),設定為20個像素值
- color :圓圈顔色,藍色(255, 0, 0)
- thickness :線的粗細,使用負值(-1),是以圓圈是實心的
(3)畫一條紅線,這條線穿過Ellie的頭,經過她的眼睛,一直到Ian的手:
# 畫一條線寬為5的紅線從x=60,y=20到x=400,y=200
output = image.copy()
cv2.line(output, (60, 20), (400, 200), (0, 0, 255), 5)
cv2.imshow("Line", output)
cv2.waitKey(0)
就像在矩形中一樣,需要兩個參數,顔色和線寬。
(4)在圖像上覆寫文本:
如果進行人臉識别,則可能需要在該人的臉上方繪制該人的名字
或者如果在計算機視覺事業中取得進步,則可以建構圖像分類器或對象檢測器,需要繪制包含類名和機率的文本。
# 在圖像上繪制文本
output = image.copy()
cv2.putText(output, "OpenCV + Jurassic Park!!!", (10, 25),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
cv2.imshow("Text", output)
cv2.waitKey(0)
putText函數的功能負責在圖像上繪制文本,需要的參數:
- img :圖像名稱
- text :要在圖像上寫/畫的文本字元串
- pt :文本的起點
- font :經常用cv2.FONT_HERSHEY_SIMPLEX字型,可以官網查閱
- scale :字型大小
- color :文字顔色
- thickness :筆劃的粗細(以像素為機關)
10.運作腳本
我使用的是vscode,右鍵-在終端中運作即可
最後貼上源代碼:
# USAGE
# python opencv_tutorial_01.py
# import the necessary packages
import imutils
import cv2
# load the input image and show its dimensions, keeping in mind that
# images are represented as a multi-dimensional NumPy array with
# shape no. rows (height) x no. columns (width) x no. channels (depth)
image = cv2.imread("jp.png")
(h, w, d) = image.shape
print("width={}, height={}, depth={}".format(w, h, d))
# display the image to our screen -- we will need to click the window
# open by OpenCV and press a key on our keyboard to continue execution
cv2.imshow("Image", image)
cv2.waitKey(0)
# access the RGB pixel located at x=50, y=100, keepind in mind that
# OpenCV stores images in BGR order rather than RGB
(B, G, R) = image[100, 50]
print("R={}, G={}, B={}".format(R, G, B))
# extract a 100x100 pixel square ROI (Region of Interest) from the
# input image starting at x=320,y=60 at ending at x=420,y=160
roi = image[60:160, 320:420]
cv2.imshow("ROI", roi)
cv2.waitKey(0)
# resize the image to 200x200px, ignoring aspect ratio
resized = cv2.resize(image, (200, 200))
cv2.imshow("Fixed Resizing", resized)
cv2.waitKey(0)
# fixed resizing and distort aspect ratio so let's resize the width
# to be 300px but compute the new height based on the aspect ratio
r = 300.0 / w
dim = (300, int(h * r))
resized = cv2.resize(image, dim)
cv2.imshow("Aspect Ratio Resize", resized)
cv2.waitKey(0)
# manually computing the aspect ratio can be a pain so let's use the
# imutils library instead
resized = imutils.resize(image, width=300)
cv2.imshow("Imutils Resize", resized)
cv2.waitKey(0)
# let's rotate an image 45 degrees clockwise using OpenCV by first
# computing the image center, then constructing the rotation matrix,
# and then finally applying the affine warp
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, -45, 1.0)
rotated = cv2.warpAffine(image, M, (w, h))
cv2.imshow("OpenCV Rotation", rotated)
cv2.waitKey(0)
# rotation can also be easily accomplished via imutils with less code
rotated = imutils.rotate(image, -45)
cv2.imshow("Imutils Rotation", rotated)
cv2.waitKey(0)
# OpenCV doesn't "care" if our rotated image is clipped after rotation
# so we can instead use another imutils convenience function to help
# us out
rotated = imutils.rotate_bound(image, 45)
cv2.imshow("Imutils Bound Rotation", rotated)
cv2.waitKey(0)
# apply a Gaussian blur with a 11x11 kernel to the image to smooth it,
# useful when reducing high frequency noise
blurred = cv2.GaussianBlur(image, (11, 11), 0)
cv2.imshow("Blurred", blurred)
cv2.waitKey(0)
# draw a 2px thick red rectangle surrounding the face
output = image.copy()
cv2.rectangle(output, (320, 60), (420, 160), (0, 0, 255), 2)
cv2.imshow("Rectangle", output)
cv2.waitKey(0)
# draw a blue 20px (filled in) circle on the image centered at
# x=300,y=150
output = image.copy()
cv2.circle(output, (300, 150), 20, (255, 0, 0), -1)
cv2.imshow("Circle", output)
cv2.waitKey(0)
# draw a 5px thick red line from x=60,y=20 to x=400,y=200
output = image.copy()
cv2.line(output, (60, 20), (400, 200), (0, 0, 255), 5)
cv2.imshow("Line", output)
cv2.waitKey(0)
# draw green text on the image
output = image.copy()
cv2.putText(output, "OpenCV + Jurassic Park!!!", (10, 25),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
cv2.imshow("Text", output)
cv2.waitKey(0)