文章來(lái)源 | 恒源云社區(qū)
原文地址 | opencv
原文作者 | instter
不逛不知道,一逛有驚喜!哈哈哈哈哈,隨手一翻,就看見(jiàn)一位版主在社區(qū)發(fā)的新論文筆記,開(kāi)屏就是顏值暴擊啊啊啊,就沖著這份暴擊,我也得不辭辛苦的搬運(yùn)出來(lái)給大家伙瞅一瞅,接下來(lái),和小編一起欣賞精彩內(nèi)容吧!
正文開(kāi)始
一、opencv簡(jiǎn)介
1 圖像的起源
1.1 圖像是什么
圖像是人類(lèi)視覺(jué)的基礎(chǔ),是自然景物的客觀(guān)反映,是人類(lèi)認(rèn)識(shí)世界和人類(lèi)本身的重要源泉?!皥D”是物體反射或透射光的分布,“像“是人的視覺(jué)系統(tǒng)所接受的圖在人腦中所形版的印象或認(rèn)識(shí),照片、繪畫(huà)、剪貼畫(huà)、地圖、書(shū)法作品、手寫(xiě)漢學(xué)、傳真、衛(wèi)星云圖、影視畫(huà)面、X光片、腦電圖、心電圖等都是圖像。—姚敏. 數(shù)字圖像處理:機(jī)械工業(yè)出版社,2014年。

1.2 模擬圖像和數(shù)字圖像
圖像起源于1826年前后法國(guó)科學(xué)家Joseph Nicéphore Niépce發(fā)明的第一張可永久保存的照片,屬于模擬圖像。==模擬圖像又稱(chēng)連續(xù)圖像==,它通過(guò)某種物理量(如光、電等)的強(qiáng)弱變化來(lái)記錄圖像亮度信息,所以是連續(xù)變換的。模擬信號(hào)的特點(diǎn)是容易受干擾,如今已經(jīng)基本全面被數(shù)字圖像替代。

1950年左右,計(jì)算機(jī)被發(fā)明,數(shù)字圖像處理學(xué)科正式誕生。
模擬圖像和數(shù)字圖像的對(duì)比,我們可以看一下:
2 數(shù)字圖像的表示
2.1 位數(shù)
計(jì)算機(jī)采用0/1編碼的系統(tǒng),數(shù)字圖像也是利用0/1來(lái)記錄信息,我們平常接觸的圖像都是8位數(shù)圖像,包含0~255灰度,其中0,代表最黑,1,表示最白。


2.2 圖像的分類(lèi)
二值圖像:
一幅二值圖像的二維矩陣僅由0、1兩個(gè)值構(gòu)成,“0”代表黑色,“1”代白色。由于每一像素(矩陣中每一元素)取值僅有0、1兩種可能,所以計(jì)算機(jī)中二值圖像的數(shù)據(jù)類(lèi)型通常為1個(gè)二進(jìn)制位。二值圖像通常用于文字、線(xiàn)條圖的掃描識(shí)別(OCR)和掩膜圖像的存儲(chǔ)。
灰度圖:
每個(gè)像素只有一個(gè)采樣顏色的圖像,這類(lèi)圖像通常顯示為從最暗黑色到最亮的白色的灰度,盡管理論上這個(gè)采樣可以任何顏色的不同深淺,甚至可以是不同亮度上的不同顏色?;叶葓D像與黑白圖像不同,在計(jì)算機(jī)圖像領(lǐng)域中黑白圖像只有黑色與白色兩種顏色;但是,灰度圖像在黑色與白色之間還有許多級(jí)的顏色深度。灰度圖像經(jīng)常是在單個(gè)電磁波頻譜如可見(jiàn)光內(nèi)測(cè)量每個(gè)像素的亮度得到的,用于顯示的灰度圖像通常用每個(gè)采樣像素8位的非線(xiàn)性尺度來(lái)保存,這樣可以有256級(jí)灰度(如果用16位,則有65536級(jí))。
彩色圖:
每個(gè)像素通常是由紅(R)、綠(G)、藍(lán)(B)三個(gè)分量來(lái)表示的,分量介于(0,255)。RGB圖像與索引圖像一樣都可以用來(lái)表示彩色圖像。與索引圖像一樣,它分別用紅(R)、綠(G)、藍(lán)(B)三原色的組合來(lái)表示每個(gè)像素的顏色。但與索引圖像不同的是,RGB圖像每一個(gè)像素的顏色值(由RGB三原色表示)直接存放在圖像矩陣中,由于每一像素的顏色需由R、G、B三個(gè)分量來(lái)表示,M、N分別表示圖像的行列數(shù),三個(gè)M x N的二維矩陣分別表示各個(gè)像素的R、G、B三個(gè)顏色分量。RGB圖像的數(shù)據(jù)類(lèi)型一般為8位無(wú)符號(hào)整形,通常用于表示和存放真彩色圖像。
3 OPENCV-PYTHON
OpenCV-Python是一個(gè)Python綁定庫(kù),旨在解決計(jì)算機(jī)視覺(jué)問(wèn)題。
Python是一種由Guido van Rossum開(kāi)發(fā)的通用編程語(yǔ)言,它很快就變得非常流行,主要是因?yàn)樗暮?jiǎn)單性和代碼可讀性。它使程序員能夠用更少的代碼行表達(dá)思想,而不會(huì)降低可讀性。
與C / C++等語(yǔ)言相比,Python速度較慢。也就是說(shuō),Python可以使用C / C++輕松擴(kuò)展,這使我們可以在C / C++中編寫(xiě)計(jì)算密集型代碼,并創(chuàng)建可用作Python模塊的Python包裝器。這給我們帶來(lái)了兩個(gè)好處:首先,代碼與原始C / C++代碼一樣快(因?yàn)樗窃诤笈_(tái)工作的實(shí)際C++代碼),其次,在Python中編寫(xiě)代碼比使用C / C++更容易。OpenCV-Python是原始OpenCV C++實(shí)現(xiàn)的Python包裝器。
OpenCV-Python使用Numpy,這是一個(gè)高度優(yōu)化的數(shù)據(jù)庫(kù)操作庫(kù),具有MATLAB風(fēng)格的語(yǔ)法。所有OpenCV數(shù)組結(jié)構(gòu)都轉(zhuǎn)換為Numpy數(shù)組。這也使得與使用Numpy的其他庫(kù)(如SciPy和Matplotlib)集成更容易。
3.1 OpenCV部署方法
安裝OpenCV之前需要先安裝numpy, matplotlib。
創(chuàng)建Python虛擬環(huán)境cv, 在cv中安裝即可。
先安裝OpenCV-Python, 由于一些經(jīng)典的算法被申請(qǐng)了版權(quán),新版本有很大的限制,所以選用3.4.3以下的版本
pip install opencv-python==3.4.2.17
現(xiàn)在可以測(cè)試下是否安裝成功,運(yùn)行以下代碼無(wú)報(bào)錯(cuò)則說(shuō)明安裝成功。
import cv2
# 讀一個(gè)圖片并進(jìn)行顯示(圖片路徑需自己指定)
lena=cv2.imread("1.jpg")
cv2.imshow("image",lena)
cv2.waitKey(0)
如果我們要利用SIFT和SURF等進(jìn)行特征提取時(shí),還需要安裝:
pip install opencv-contrib-python==3.4.2.17
3.2 OPENCV的模塊
下圖列出了OpenCV中包含的各個(gè)模塊:

其中core、highgui、imgproc是最基礎(chǔ)的模塊,該課程主要是圍繞這幾個(gè)模塊展開(kāi)的,分別介紹如下:
- core模塊實(shí)現(xiàn)了最核心的數(shù)據(jù)結(jié)構(gòu)及其基本運(yùn)算,如繪圖函數(shù)、數(shù)組操作相關(guān)函數(shù)等。
- highgui模塊實(shí)現(xiàn)了視頻與圖像的讀取、顯示、存儲(chǔ)等接口。
- imgproc模塊實(shí)現(xiàn)了圖像處理的基礎(chǔ)方法,包括圖像濾波、圖像的幾何變換、平滑、閾值分割、形態(tài)學(xué)處理、邊緣檢測(cè)、目標(biāo)檢測(cè)、運(yùn)動(dòng)分析和對(duì)象跟蹤等。
對(duì)于圖像處理其他更高層次的方向及應(yīng)用,OpenCV也有相關(guān)的模塊實(shí)現(xiàn)
- features2d模塊用于提取圖像特征以及特征匹配,nonfree模塊實(shí)現(xiàn)了一些專(zhuān)利算法,如sift特征。
- objdetect模塊實(shí)現(xiàn)了一些目標(biāo)檢測(cè)的功能,經(jīng)典的基于Haar、LBP特征的人臉檢測(cè),基于HOG的行人、汽車(chē)等目標(biāo)檢測(cè),分類(lèi)器使用Cascade Classification(級(jí)聯(lián)分類(lèi))和Latent SVM等。
- stitching模塊實(shí)現(xiàn)了圖像拼接功能。
- FLANN模塊(Fast Library for Approximate Nearest Neighbors),包含快速近似最近鄰搜索FLANN 和聚類(lèi)Clustering算法。
- ml模塊機(jī)器學(xué)習(xí)模塊(SVM,決策樹(shù),Boosting等等)。
- photo模塊包含圖像修復(fù)和圖像去噪兩部分。
- video模塊針對(duì)視頻處理,如背景分離,前景檢測(cè)、對(duì)象跟蹤等。
- calib3d模塊即Calibration(校準(zhǔn))3D,這個(gè)模塊主要是相機(jī)校準(zhǔn)和三維重建相關(guān)的內(nèi)容。包含了基本的多視角幾何算法,單個(gè)立體攝像頭標(biāo)定,物體姿態(tài)估計(jì),立體相似性算法,3D信息的重建等等。
- G-API模塊包含超高效的圖像處理pipeline引擎
二、opencv基本操作
1 圖像的IO操作
這里我們會(huì)給大家介紹如何讀取圖像,如何顯示圖像和如何保存圖像。
1.1 讀取圖像
API
cv.imread()
參數(shù):
要讀取的圖像
讀取方式的標(biāo)志
1??cv.IMREADCOLOR:以彩色模式加載圖像,任何圖像的透明度都將被忽略。這是默認(rèn)參數(shù)。
2??cv.IMREADGRAYSCALE:以灰度模式加載圖像
3?? cv.IMREAD_UNCHANGED:包括alpha通道的加載圖像模式。
可以使用1、0或者-1來(lái)替代上面三個(gè)標(biāo)志參考代碼
import numpy as np
import cv2 as cv
# 以灰度圖的形式讀取圖像
img = cv.imread('messi5.jpg',0)
1.2顯示圖像
API
cv.imshow()
參數(shù):
顯示圖像的窗口名稱(chēng),以字符串類(lèi)型表示
要加載的圖像
注意:在調(diào)用顯示圖像的API后,要調(diào)用cv.waitKey()給圖像繪制留下時(shí)間,否則窗口會(huì)出現(xiàn)無(wú)響應(yīng)情況,并且圖像無(wú)法顯示出來(lái)。
另外我們也可使用matplotlib對(duì)圖像進(jìn)行展示。參考代碼
# opencv中顯示
cv.imshow('image',img)
cv.waitKey(0)
# matplotlib中展示
plt.imshow(img[:,:,::-1])
1.3 保存圖像
API
cv.imwrite()
參數(shù):
- 文件名,要保存在哪里
- 要保存的圖像
參考代碼:
cv.imwrite('messigray.png',img)
1.4 總結(jié)
我們通過(guò)加載灰度圖像,顯示圖像,如果按’s’并退出則保存圖像,或者按ESC鍵直接退出而不保存。
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1 讀取圖像
img = cv.imread('messi5.jpg',0)
# 2 顯示圖像
# 2.1 利用opencv展示圖像
cv.imshow('image',img)
# 2.2 在matplotplotlib中展示圖像
plt.imshow(img[:,:,::-1])
plt.title('匹配結(jié)果'), plt.xticks([]), plt.yticks([])
plt.show()
k = cv.waitKey(0)
# 3 保存圖像
cv.imwrite('messigray.png',img)
2 繪制幾何圖形
2.1 繪制直線(xiàn)
cv.line(img,start,end,color,thickness)
參數(shù):
- 列img:要繪制直線(xiàn)的圖像
- 列Start,end: 直線(xiàn)的起點(diǎn)和終點(diǎn)
- 列color: 線(xiàn)條的顏色
- 列Thickness: 線(xiàn)條寬度
2.2 繪制圓形
cv.circle(img,centerpoint, r, color, thickness)
參數(shù):
- img:要繪制圓形的圖像
- Centerpoint, r: 圓心和半徑
- color: 線(xiàn)條的顏色
- Thickness: 線(xiàn)條寬度,為-1時(shí)生成閉合圖案并填充顏色
2.3 繪制矩形
cv.rectangle(img,leftupper,rightdown,color,thickness)
參數(shù):
- img:要繪制矩形的圖像
- Leftupper, rightdown: 矩形的左上角和右下角坐標(biāo)
- color: 線(xiàn)條的顏色
- Thickness: 線(xiàn)條寬度
2.4 向圖像中添加文字
cv.putText(img,text,station, font, fontsize,color,thickness,cv.LINE_AA)
參數(shù):
- img: 圖像
- text:要寫(xiě)入的文本數(shù)據(jù)
- station:文本的放置位置
- font:字體
- Fontsize :字體大小
2.5 效果展示
我們生成一個(gè)全黑的圖像,然后在里面繪制圖像并添加文字
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1 創(chuàng)建一個(gè)空白的圖像
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('匹配結(jié)果'), plt.xticks([]), plt.yticks([])
plt.show()
結(jié)果:
3 獲取并修改圖像中的像素點(diǎn)
我們可以通過(guò)行和列的坐標(biāo)值獲取該像素點(diǎn)的像素值。對(duì)于BGR圖像,它返回一個(gè)藍(lán),綠,紅值的數(shù)組。對(duì)于灰度圖像,僅返回相應(yīng)的強(qiáng)度值。使用相同的方法對(duì)像素值進(jìn)行修改。
import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg')
# 獲取某個(gè)像素點(diǎn)的值
px = img[100,100]
# 僅獲取藍(lán)色通道的強(qiáng)度值
blue = img[100,100,0]
# 修改某個(gè)位置的像素值
img[100,100] = [255,255,255]
4 獲取圖像的屬性
圖像屬性包括行數(shù),列數(shù)和通道數(shù),圖像數(shù)據(jù)類(lèi)型,像素?cái)?shù)等。
5 圖像通道的拆分與合并
有時(shí)需要在B,G,R通道圖像上單獨(dú)工作。在這種情況下,需要將BGR圖像分割為單個(gè)通道?;蛘咴谄渌闆r下,可能需要將這些單獨(dú)的通道合并到BGR圖像。你可以通過(guò)以下方式完成。
# 通道拆分
b,g,r = cv.split(img)
# 通道合并
img = cv.merge((b,g,r))
6 色彩空間的改變
OpenCV中有150多種顏色空間轉(zhuǎn)換方法。最廣泛使用的轉(zhuǎn)換方法有兩種,BGR<=>Gray和BGR<=>HSV。
cv.cvtColor(input_image,flag)
參數(shù):
- input_image: 進(jìn)行顏色空間轉(zhuǎn)換的圖像
- flag: 轉(zhuǎn)換類(lèi)型
1??cv.COLOR_BGR2GRAY : BGR<=>Gray
2??cv.COLOR_BGR2HSV: BGR→HSV
三、算術(shù)操作
1.圖像的加法
你可以使用OpenCV的cv.add()函數(shù)把兩幅圖像相加,或者可以簡(jiǎn)單地通過(guò)numpy操作添加兩個(gè)圖像,如res = img1 + img2。兩個(gè)圖像應(yīng)該具有相同的大小和類(lèi)型,或者第二個(gè)圖像可以是標(biāo)量值。
注意:OpenCV加法和Numpy加法之間存在差異。OpenCV的加法是飽和操作,而Numpy添加是模運(yùn)算。
參考以下代碼:
>>> x = np.uint8([250])
>>> y = np.uint8([10])
>>> print( cv.add(x,y) ) # 250+10 = 260 => 255
[[255]]
>>> print( x+y ) # 250+10 = 260 % 256 = 4
[4]
這種差別在你對(duì)兩幅圖像進(jìn)行加法時(shí)會(huì)更加明顯。OpenCV 的結(jié)果會(huì)更好一點(diǎn)。所以我們盡量使用 OpenCV 中的函數(shù)。
我們將下面兩幅圖像:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1 讀取圖像
img1 = cv.imread("view.jpg")
img2 = cv.imread("rain.jpg")
# 2 加法操作
img3 = cv.add(img1,img2) # cv中的加法
img4 = img1+img2 # 直接相加
# 3 圖像顯示
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img3[:,:,::-1])
axes[0].set_title("cv中的加法")
axes[1].imshow(img4[:,:,::-1])
axes[1].set_title("直接相加")
plt.show()
結(jié)果
2.圖像的混合
這其實(shí)也是加法,但是不同的是兩幅圖像的權(quán)重不同,這就會(huì)給人一種混合或者透明的感覺(jué)。圖像混合的計(jì)算公式如下:
通過(guò)修改 α 的值(0 → 1),可以實(shí)現(xiàn)非常炫酷的混合。
現(xiàn)在我們把兩幅圖混合在一起。第一幅圖的權(quán)重是0.7,第二幅圖的權(quán)重是0.3。函數(shù)cv2.addWeighted()可以按下面的公式對(duì)圖片進(jìn)行混合操作。
這里γ取為零。
參考以下代碼:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1 讀取圖像
img1 = cv.imread("view.jpg")
img2 = cv.imread("rain.jpg")
# 2 圖像混合
img3 = cv.addWeighted(img1,0.7,img2,0.3,0)
# 3 圖像顯示
plt.figure(figsize=(8,8))
plt.imshow(img3[:,:,::-1])
plt.show()
