opencv-python學習之旅

2022-12-29 06:00:43

opencv-python 操作


*注:在此筆記中只記錄下各種函數的使用,規則
詳細講解見https://s3.ap-northeast-1.wasabisys.com/img.tw511.com/202212/22h2r2q5b4f',0) cv.imshow('image',img) k = cv.waitKey(0) if k == 27: # ESC 退出 cv.destroyAllWindows() elif k == ord('s'): # 's' 儲存退出 cv.imwrite('messigray.png',img) cv.destroyAllWindows()

Note

有一種特殊情況,你可以先建立一個視窗然後載入影象到該視窗。在這種情況下,你能指定視窗是否可調整大小。它是由這個函數完成的 cv.namedWindow()。預設情況下,flag 是 cv.WINDOW_AUTOSIZE。但如果你指定了 flag 為 cv.WINDOW_NORMAL,你能調整視窗大小。當影象尺寸太大,在視窗中新增跟蹤條是很有用的。

看下面的程式碼:

cv.namedWindow('image', cv.WINDOW_NORMAL)
cv.imshow('image',img)
cv.waitKey(0)
cv.destroyAllWindows()

儲存影象

儲存影象,用這個函數 cv.imwrite()

第一個引數是檔名,第二個引數是你要儲存的影象。

cv.imwrite('messigray.png',img)

將該影象用 PNG 格式儲存在工作目錄。

使用 Matplotlib

Matplotlib 是一個 Python 的繪相簿,提供了豐富多樣的繪圖函數。你將在接下來的文章中看到它們。在這裡,你將學習如何使用 Matplotlib 來顯示影象。你還能用 Matplotlib 縮放影象,儲存影象等。

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt

img = cv.imread('messi5.jpg',0)
plt.imshow(img, cmap = 'gray', interpolation = 'bicubic')   # 讓影象以灰色形式展示
# 或者選擇  plt.imshow(img[:,:,::-1])    #這一步操作,保證和原影象顯示的色彩一致
plt.xticks([]), plt.yticks([]) # 隱藏 X 和 Y 軸的刻度值  去掉則會顯示刻度
plt.show()

色彩模式與cv2不一樣(BGR),因此顯示出來的顏色不對,需要改一下

plt.imshow(img[:,:,::-1])    #這一步操作,保證和原影象顯示的色彩一致
plt.show()

影象的繪製功能

畫線

去畫一條線,你需要傳遞線條的開始和結束的座標。我們將建立一個黑色影象,並在坐上角到右下角畫一條藍色的線

import numpy as np
import cv2 as cv
# 建立一個黑色的影象
img = np.zeros((512,512,3), np.uint8)
# 畫一條 5px 寬的藍色對角線
cv.line(img,(0,0),(511,511),(255,0,0),5)

cv2.line(影象,(起始座標),(終點座標),(顏色),寬度)

畫圓

畫一個圓,你需要它的圓心和半徑。我們將在上面繪製的矩形上畫一個內圓。

cv.circle(img,(447,63), 63, (0,0,255), -1)

cv.circle(影象,(圓心座標x,y),半徑,(顏色),載入方式)

畫橢圓

畫一個橢圓,你需要傳好幾個引數。一個引數是圓心位置 (x,y)。下個引數是軸的長度 (長軸長度,短軸長度)。角度是橢圓在你逆時針方向的旋轉角度。startAngle 和 endAngle 表示從長軸順時針方向測量的橢圓弧的起點和終點。如整圓就傳 0 和 360。更多細節請看 cv.ellipse() 的檔案。下面是在這個影象中間畫的一個半橢圓例子。

cv.ellipse(img,(256,256),(100,50),0,0,180,(0,255,255),-1)

cv.ellipse(影象,(圓心座標),(長軸,短軸),起時角度,起點,終點,顏色,載入方式

畫矩形

cv.rectangle(img,左上角座標,右下角座標,顏色,線條厚度)

畫多邊形

畫多邊形,首先你需要頂點的做座標。將這些點組成一個形狀為 ROWSx1x2 的陣列,ROWS 是頂點數,它應該是 int32 型別。這裡我們繪製一個頂點是黃色的小多邊形。

pts = np.array([[10,5],[20,30],[70,20],[50,10]], np.int32)
pts = pts.reshape((-1,1,2))
cv.polylines(img,[pts],True,(0,255,255))

Note

  • 如果地三個是 False,你將獲得所有點的折線,而不是一個閉合形狀。
  • cv.polylines() 能畫很多線條。只需建立你想繪製所有線條的列表,然後將其傳給這個函數。所有線條都將單獨繪製。繪製一組線條比呼叫 cv.line() 好很多,快很多。

繪圖新增文字

cv.putText(img,輸入內容,文字的放置位置,字型,字型大小,顏色,線條寬度,cv.LINE__AA)

存取並修改畫素點

通過行列座標來進行存取及修改

黃色為綠色和紅色的混合。所以,該影象的所有畫素值都應為R=255,G=255,B=0。

>>> import numpy as np
>>> import CV2
>>> img = CV2.imread("img/yellow.jpg")
>>> h,w,c = img.shape
#影象大小為128*128*3
>>> print(h,w,c)
128 128 3
px = img[100,100]     # 獲取某個點的畫素值

從上面的程式碼中可以看到,您可以通過行和列座標存取畫素值。注意,對於常見的RGB 影象,OpenCV的imread函數返回的是一個藍色(Blue)值、綠色(Green)值、紅色(Red)值的陣列,維度大小為3。而對於灰度影象,僅返回相應的灰度值。

>>> img[100,100]
#OpenCV的讀取順序為B,G,R,由於影象所有畫素為黃色,因此,G=255,R=255
array([  0, 255, 255], dtype=uint8)

# 僅存取藍色通道的畫素
>>> blue = img[100,100,0]
>>> print(blue)
0

你也可以使用同樣的方法來修改畫素值。

>>> img[100,100] = [255,255,255]
>>> print(img[100,100])
[255 255 255]

存取屬性

影象大小

img.shape      # 變數.shape

(256,256,3)

img.shape[:2] 取彩色圖片的長、寬。

  • 使用彩色模式傳參時
cols,rows = img.shape[:2]
# 或者
cols,rows,x = img.shape
  • 使用灰色模式

    cols ,rows = img.shape
    

如果img.shape[:3] 則取彩色圖片的長、寬、通道

關於img.shape[0]、[1]、[2]
img.shape[0]:影象的垂直尺寸(高度)
img.shape[1]:影象的水平尺寸(寬度)
img.shape[2]:影象的通道數

資料型別

img.dtype

dtype('uint8')

畫素點數量

img.size

196608

影象的裁剪、拼接、翻轉、縮放等 [(https://blog.csdn.net/zh_jessica/article/details/77946346)]

縮放:

一、影象縮放
影象縮放主要使用resize函數

result = cv2.resize(src, dsize[, result[. fx[, fy[, interpolation]]]]) 記得要用新變數來接收
其中src表示原始影象,dsize表示縮放大小,fx和fy也可以表示縮放大小倍數,他們兩個(dsize或fx\fy)設定一個即可實現影象縮放

引數說明:

src - 原圖

dst - 目標影象。當引數dsize不為0時,dst的大小為size;否則,它的大小需要根據src的大小,引數fx和fy決定。dst的型別(type)和src影象相同

dsize - 目標影象大小。當dsize為0時,它可以通過以下公式計算得出:

所以,引數dsize和引數(fx, fy)不能夠同時為0

fx - 水平軸上的比例因子。當它為0時,計算公式如下:

fy - 垂直軸上的比例因子。當它為0時,計算公式如下:

interpolation - 插值方法。共有5種:
INTER_NEAREST - 最近鄰插值法
INTER_LINEAR - 雙線性插值法(預設)
INTER_AREA - 基於區域性畫素的重取樣(resampling using pixel area relation)。對於影象抽取也叫縮小影象(image decimation)來說,這可能是一個更好的方法。但如果是放大影象時,它和最近鄰法的效果類似。
INTER_CUBIC - 基於4x4畫素鄰域的3次插值法
INTER_LANCZOS4 - 基於8x8畫素鄰域的Lanczos插值

縮小影象 用INTER_AREA更好,放大影象用 INTER_CUBIC更好;
————————————————

程式碼如下:

import cv2

#讀取圖片
image = cv2.imread("E:/pythonProject/xin.jpeg")

#圖片縮放
image1 = cv2.resize(image, (200,200))     

#圖片顯示
cv2.imshow("resize", image1)
cv2.imshow("image", image)

#等待視窗
cv2.waitKey(0)

旋轉

opencv中對影象的旋轉主要是先通過getRotationMatrix2D函數得到影象的旋轉矩陣,然後再通過仿射變換函數warpAffine得到旋轉後的影象。

函數說明:

cv2.getRotationMatrix2D(center, angle, scale)
cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst

引數說明:

getRotationMatrix2D: 得到影象的旋轉矩陣

center–表示旋轉的中心點
angle–表示旋轉的角度degrees
scale–影象縮放因子
warpAffine:

src – 輸入的影象
M – 2 X 3 的變換矩陣.
dsize – 輸出的影象的size大小
dst – 輸出的影象
flags – 輸出影象的插值方法
borderMode – 影象邊界的處理方式
borderValue – 當影象邊界處理方式為BORDER_CONSTANT 時的填充值
程式碼示範:

img = cv2.imread('messi5.jpg',0)
rows,cols = img.shape
#90度旋轉

M = cv2.getRotationMatrix2D((cols/2,rows/2),90,1)
dst = cv2.warpAffine(img,M,(cols,rows))

平移

  1. 平移translate
    平移通過自定義平移矩陣以及函數warpAffine實現:

程式碼示範:

img = cv2.imread('messi5.jpg',0)
rows,cols = img.shape
# 平移矩陣M:[[1,0,x],[0,1,y]]
M = np.float32([[1,0,100],[0,1,50]])
dst = cv2.warpAffine(img,M,(cols,rows))

反轉

  1. 翻轉flip
    翻轉通過函數flip實現:

函數說明:

cv2.flip(src, flipCode[, dst]) → dst
1
引數說明:

src – 輸入的影象
dst – 輸出的影象
flipCode – 翻轉模式,flipCode==0垂直翻轉(沿X軸翻轉),flipCode>0水平翻轉(沿Y軸翻轉),flipCode<0水平垂直翻轉(先沿X軸翻轉,再沿Y軸翻轉,等價於旋轉180°)
程式碼示範:

# 水平翻轉
flip_horiz_img = cv2.flip(pad_img, 1)
# 垂直翻轉
flip_verti_img = cv2.flip(pad_img, 0)
# 水平垂直翻轉
flip_horandver_img = cv2.flip(pad_img, -1)

拼接

單個影象多次拼接

import  cv2
img =cv2.imread(file_path[i])
img=cv2.hconcat([img,img,img])#水平拼接
img=cv2.vconcat([img,img,img])#垂直拼接

多個相似特徵影象拼接(開擺!)

import cv2
import numpy as np
 
 
def stitch(image):
    # 影象拼接
    # stitcher = cv2.createStitcher(False)  # OpenCV 3.X.X.X使用該方法
    stitcher = cv2.Stitcher_create(cv2.Stitcher_PANORAMA)  # OpenCV 4.X.X.X使用該方法,cv2.Stitcher_create()也可以
    status, pano = stitcher.stitch(image)
 
    # 黑邊處理
    if status == cv2.Stitcher_OK:
        # 全景圖輪廓提取
        stitched = cv2.copyMakeBorder(pano, 10, 10, 10, 10, cv2.BORDER_CONSTANT, (0, 0, 0))
        gray = cv2.cvtColor(stitched, cv2.COLOR_BGR2GRAY)
        thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)[1]
        cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
 
        # 輪廓最小正矩形
        mask = np.zeros(thresh.shape, dtype="uint8")
        (x, y, w, h) = cv2.boundingRect(cnts[0])  # 取出list中的輪廓二值圖,型別為numpy.ndarray
        cv2.rectangle(mask, (x, y), (x + w, y + h), 255, -1)
 
        # 腐蝕處理,直到minRect的畫素值都為0
        minRect = mask.copy()
        sub = mask.copy()
        while cv2.countNonZero(sub) > 0:
            minRect = cv2.erode(minRect, None)
            sub = cv2.subtract(minRect, thresh)
 
        # 提取minRect輪廓並裁剪
        cnts = cv2.findContours(minRect, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
        (x, y, w, h) = cv2.boundingRect(cnts[0])
        stitched = stitched[y:y + h, x:x + w]
 
        cv2.imshow('stitched', stitched)
        cv2.imwrite('stitched.jpg', stitched)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    else:
        print('影象匹配的特徵點不足')
 
 
if __name__ == "__main__":
    image1 = cv2.imread('data/space1.jpg')
    image2 = cv2.imread('data/space2.jpg')
    image3 = cv2.imread('data/space3.jpg')
    image = image1, image2, image3
    stitch(image)

(18條訊息) OpenCV-Python 影象全景拼接stitch及黑邊處理_Klein-的部落格-CSDN部落格_stitcher_create