圖像處理學習筆記(一)
- 1 OpenCV簡介:
-
- 1.1 圖像處理簡介:
-
-
- 1.圖像是什麼?
- 2.模拟圖像和數字圖像?
- 3.數字圖像?
-
- 1.2 OpenCV簡介及安裝方法:
-
-
- 優勢:
- OpenCV-python:
- OpenCV部署方法:
-
- 1.3 OpenCV的子產品:
- 2 OpenCV基本操作:
-
- 2.1 圖像的IO操作:
-
- 2.1.1 讀取圖像:
- 2.1.2 顯示圖像:
- 2.1.3 儲存圖像:
- 2.1.4 完整代碼:
- 2.2 繪制幾何圖形:
-
- 2.2.1 繪制直線:
- 2.2.2 繪制圓形:
- 2.2.3 繪制矩形:
- 2.2.4 在圖像中添加文字:
- 2.2.5 效果展示:
- 2.3 擷取并修改圖像中的像素點:
- 2.4 基本屬性:
- 2.5 通道拆分與合并:
- 2.6 色彩空間的改變:
- 3 算術操作:
-
- 3.1 圖像的加法:
- 3.2 圖像的混合:
- 4 OpenCV圖像處理:
-
- 4.1 幾何變換:
-
- 4.1.1 圖像縮放:
- 4.1.2 圖像平移:
- 4.1.3 圖像旋轉:
- 4.1.4 圖像的仿射變換:
- 4.1.5 圖像的透射變換:
- 4.1.6 圖像金字塔:
- 4.1.7 幾何變換總結:
哔哩哔哩:《黑馬程式員人工智能教程_10小時學會圖像處理OpenCV入門教程》
1 OpenCV簡介:
1.1 圖像處理簡介:
1.圖像是什麼?
圖:物體反射或透射光的分布
像:人的視覺系統所接受的圖在人腦中所形成的印象或認識
2.模拟圖像和數字圖像?
模拟圖像:連續存儲的資料
數字圖像:分級存儲的資料
3.數字圖像?
位數:圖像的表示,常見是8位
分類:二值圖像、灰階圖像和彩色圖像

1.2 OpenCV簡介及安裝方法:
OpenCV是一款由Intel公司俄羅斯團隊發起并參與和維護的一個計算機視覺處理開源軟體庫,支援與計算機視覺和機器學習相關的衆多算法。
優勢:
- 程式設計語言:基于C++實作,提供python、MATLAB等語言接口,OpenCV-python是OpenCV的python API,結合了OpenCV C++ API和python語言的最佳特性。
- 跨平台:
- 活躍的開發團隊
- 豐富的API:完善的傳統計算機視覺算法,涵蓋主流的機器學習算法,并同時添加了對深度學習的支援。
OpenCV-python:
- 是一個python綁定庫,旨在解決計算機視覺問題。
- 使用numpy
OpenCV部署方法:
- 需要先安裝numpy,matplotlib
- 建立虛拟環境
參考:https://www.jianshu.com/p/453184d63fb7
- 安裝OpenCV-python,由于一些經典的算法被申請了版權,新版本有很大限制,是以選用3.4.3以下的版本
- (不過我用conda或者pip都找不到3.4.2.17的,索性就沒加版本号,下載下傳的是4.5的版本,先用着吧)
pip install opencv-python==3.4.2.17
conda install opencv-python==3.4.2.17
- 安裝過程中一般會出現問題,請參考:
使用anaconda安裝出現:PackagesNotFoundError: The following packages are not available from current channels
使用pip安裝包時,出現Cannot unpack file xxx的問題的解決以及pip安裝速度慢或出現readtime out問題的解決。
- 運作一下,看看有無毛病,我的可以了,真不戳。
import cv2
lena = cv2.imread('1.jpg')
cv2.imshow('image',lena)
cv2.waitKey(0)
- 如果我們要用SIFT和SURF進行特征提取,還需要安裝:
pip install opencv-contrib-python==3.4.2.17
1.3 OpenCV的子產品:
其中core、highgui、imgproc是最基礎的子產品,介紹如下:
- core子產品實作了最核心的資料結構及其基本運算,如繪圖函數、數組操作相關函數。
- highgui實作了視訊與圖像的讀取、顯示、存儲等接口
- imgproc實作了圖像處理的基礎方法,包括圖像濾波、圖像的幾何變換平滑、門檻值分割、形态學處理、邊緣檢測、目标檢測、運動分析和對象跟蹤等。
總結:
- opencv的子產品:
core:最核心的資料結構
highgui:視訊與圖像的讀取、顯示、存儲
imgproc:圖像處理的基礎方法
features2d:圖像特征以及特征比對
2 OpenCV基本操作:
主要内容:
- 圖像的IO操作,讀取和儲存方法
- 在圖像上繪制幾何圖形
- 擷取圖像的屬性
- 通路圖像的像素,進行通道分離、合并等
- 實作顔色空間的轉換
- 圖像的算術運算
2.1 圖像的IO操作:
2.1.1 讀取圖像:
2.1.2 顯示圖像:
# opencv顯示
import cv2
img = cv2.imread('1.jpg',0)
cv2.imshow('image',img)
cv2.waitKey(0)
# matplotlib顯示
#img是以BGR通道順序存儲,而plt是以RGB的順序,這裡是要實作通道順序轉換
# plt.show(img[:,:,::-1])
2.1.3 儲存圖像:
2.1.4 完整代碼:
import cv2 as cv
import matplotlib.pyplot as plt
# 1.讀取圖像
img = cv.imread('1.jpg',0)
# 2.顯示圖像
# 2.1 opencv顯示
# cv.imshow('image',img)
# cv.waitKey(0)
# 2.2 matplotlib顯示
plt.imshow(img,cmap=plt.cm.gray) #讀取灰階圖
plt.show()
# 3.圖像儲存
cv.imwrite('2.png',img)
2.2 繪制幾何圖形:
2.2.1 繪制直線:
2.2.2 繪制圓形:
2.2.3 繪制矩形:
2.2.4 在圖像中添加文字:
2.2.5 效果展示:
生成一個全黑的圖像,然後在裡面繪制圖像并添加文字
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
# 1.建立一個空白的圖像
img = np.zeros((512,512,3),np.uint8)
# 2.繪制圖形
cv.line(img,(0,0),(511,511),(255,0,0),5)
cv.rectangle(img,(384,0),(510,128),(0,255,0),3)
cv.circle(img,(447,63),63,(0,0,255),-1)
font = cv.FONT_HERSHEY_SIMPLEX
cv.putText(img,'OpenCV',(10,500),font,4,(255,255,255),2,cv.LINE_AA)
# 3.圖像展示
plt.imshow(img[:,:,::-1])
plt.title('Result')
plt.xticks([]),plt.yticks([]) #将圖的橫縱坐标刻度設定為空
plt.show()
2.3 擷取并修改圖像中的像素點:
- 通過行和列的坐标值擷取該像素點的像素值。對于BGR圖像它傳回一個藍,綠,紅值的數組,對于灰階圖像,僅傳回相應的強度值。
- (不知道為什麼當我單步運作時,會報錯,整體一起就沒事)
import cv2 as cv
img = cv.imread('1.jpg')
# 擷取某個像素點的值
px1 = img[100,100]
# 僅擷取藍色通道的強度值
blue = img[100,100,0]
# 修改某個位置的像素值
img[100,100] = [255,255,255]
2.4 基本屬性:
# print(img.shape)
# print(img.dtype)
# print(img.size)
2.5 通道拆分與合并:
# 通道拆分
b,g,r = cv.split(img)
# 通道合并
img = cv.merge((b,g,r))
2.6 色彩空間的改變:
opencv有150多種顔色空間轉換的方法。最廣泛使用的轉換方法有兩種,BGR<=>Gray 和BGR<=>HSV
既然前面已經是轉為灰階圖了,為什麼還是需要cmap參數呢?
不加cmap的話,還是不夠灰色的,求解!!!
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
plt.imshow(gray,cmap=plt.cm.gray)
plt.show()
hsv = cv.cvtColor(img,cv.COLOR_BGR2HSV)
plt.imshow(hsv)
plt.show()
不加cmap
加cmap=plt.cm.gray
hsv圖
3 算術操作:
3.1 圖像的加法:
import cv2 as cv
import numpy as np
x = np.uint8([250])
y = np.uint8([10])
print(cv.add(x,y)) # 250+10 = 260 =>255
print(x+y) # 250+10 = 260 % 256 => 4
兩個大小不一樣的圖像相加:
(參考:用OpenCV合成PNG和JPG圖檔)
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img1 = cv.imread('1.jpg',1)
img2 = cv.imread('rabbit.png',1)
width = int((1440 - 1090) / 2)
height = int((1080 - 720) / 2)
img1 = img1[height:height + 720, width:width + 1090]
img_res = cv.add(img1,img2)
plt.imshow(img_res)
plt.show()
通過cv.add(img1,img2)
img1+img2—直接相加
3.2 圖像的混合:
其實也是加法,但是兩者的權重不同,給人一種混合的或者透明的感覺。圖像混合的計算公式如下:
g(x) = (1-α)f0(x) + αf1(x)
通過修改α的值0 ==> 1,可以實作炫酷的組合。
dst = k1img1 + k2img2 + b
cv.addWeighted(img1,k1,img2,k2,b)
4 OpenCV圖像處理:
4.1 幾何變換:
4.1.1 圖像縮放:
import cv2 as cv
import matplotlib.pyplot as plt
img = cv.imread('1.jpg')
rows,cols = img.shape[:2]
res1 = cv.resize(img,(2*rows,2*cols))
print(res1.shape)
res2 = cv.resize(img,None,fx=0.5,fy=0.5)
print(res2.shape)
4.1.2 圖像平移:
# 2、圖像平移
M = np.float32([[1,0,100],[0,1,50]])
img = cv.imread('1.jpg')
rows,cols = img.shape[:2]
res = cv.warpAffine(img,M,(cols,rows))
plt.imshow(res[:,:,::-1])
plt.show()
4.1.3 圖像旋轉:
除了改變圖像内像素點的位置,還要修正原點的位置(因為原點的位置跟着動了)
# 3、圖像旋轉
# 讀取圖像
img = cv.imread('1.jpg')
# 圖像旋轉
# (1)擷取寬度(列數)、高度(行數)
rows,cols = img.shape[:2]
# (2)生成旋轉矩陣
# (cols/2,rows/2):指定旋轉中心
# 45:旋轉角度
# 1:縮放比例,1代表原大小
M = cv.getRotationMatrix2D((cols/2,rows/2),45,1)
# (3)旋轉變換
dst = cv.warpAffine(img,M,(cols,rows))
# 3 圖像展示
fig,axes = plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img[:,:,::-1])
axes[0].set_title('Start')
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title('Process')
plt.show()
結果圖:
4.1.4 圖像的仿射變換:
待求解矩陣中有六個未知量,我們給定前後各三組點,這樣就得到六個方程,就可以解方程了。
# 圖像仿射變換
# 1、讀取圖像
img = cv.imread('1.jpg')
# 2、仿射變換
rows,cols = img.shape[:2]
# 2.1 建立變換矩陣
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[100,100],[200,50],[100,250]])
M = cv.getAffineTransform(pts1,pts2)
# 2.2 完成仿射變換
dst = cv.warpAffine(img,M,(cols,rows))
# 3、圖像顯示
fig,axes = plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img[:,:,::-1])
axes[0].set_title('Start')
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title('Process')
plt.show()
效果圖:
4.1.5 圖像的透射變換:
透射變換是指利用透視中心、像點、目标點三點共線的條件,按透視旋轉定律使承影面(透視面)繞迹線(透視軸)旋轉某一角度,破壞原有的投影光線束,仍能保持承影面上投影幾何圖形不變的變換。
經過之前仿射變換介紹為什麼要三組點(因為有六個未知數,需要留個方程),那現在是八個未知數,是以需要四組點了。
# 圖像透射變換
# 1、讀取圖像
img = cv.imread('1.jpg')
# 2、透射變換
rows,cols = img.shape[:2]
# 2.1 建立變換矩陣
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[100,145],[300,100],[80,290],[310,300]])
T = cv.getPerspectiveTransform(pts1,pts2)
# 2.2 完成仿射變換
dst = cv.warpPerspective(img,T,(cols,rows))
# 3、圖像顯示
fig,axes = plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img[:,:,::-1])
axes[0].set_title('Start')
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title('Process')
plt.show()
效果圖(也不知道這是怎麼個透法):
4.1.6 圖像金字塔:
- 圖像金字塔是圖像多尺度表達的一種,最主要用于圖像的分割,是一種以多分辨率來解釋圖像的有效但概念簡單的結構。
- 圖像金字塔用于機器視覺和圖像壓縮,一幅圖像的金字塔是一系列以金字塔形狀排列的分辨率逐漸降低,且來源于同一張原始圖的圖像集合。其通過梯次向下采樣取得,直到達到某個終止條件才停止采樣。
- 金字塔的底部是待處理圖像的高分辨率表示,而頂部是低分辨率的近似,層級越高,圖像越小,分辨率越低。
API:
# 圖像金字塔
# 1 圖像讀取
img = cv.imread('rabbit.png')
# 2 進行圖像采樣
up_img = cv.pyrUp(img)
down_img = cv.pyrDown(img)
# 3 圖像顯示
cv.imshow('up_img',up_img)
cv.imshow('img',img)
cv.imshow('down_img',down_img)
cv.waitKey(0)
效果圖:
4.1.7 幾何變換總結:
- 圖像縮放:cv.resize()
- 圖像平移:指定平移矩陣後,開始平移cv.warpAffine()
- 圖像旋轉:擷取旋轉矩陣cv.getRotationMatrix2D(),開始旋轉cv.warpAffine()
- 仿射變換:調用cv.getAffineTransform()建立變換矩陣,最後給cv.warpAffine()
- 透射變換:調用cv.getPerspectiveTransform()建立變換矩陣,最後給cv.warpPerspective()
- 圖像金字塔:cv.pyrUp(),cv.pyrDown()