日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python 图像无缝拼接,OpenCV Python 系列教程3 - Core 组件

發(fā)布時(shí)間:2024/8/5 python 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python 图像无缝拼接,OpenCV Python 系列教程3 - Core 组件 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

基本知識(shí)

灰度圖像的存儲(chǔ)方式:

image

多通道圖像存儲(chǔ)方式

image

OpenCV 中的通道存儲(chǔ)為 BGR

像素值的存儲(chǔ)方式

RGB 模式,顯示設(shè)備采用這種模式

HSV、HLS 將顏色分解成色調(diào)、飽和度和亮度/明度

YCrCb 在 JPEG 圖像格式中廣泛使用

CIE Lab* 是一種感知上均勻的顏色空間,它適用來度量?jī)蓚€(gè)顏色之間的距離

圖片的基本操作

學(xué)習(xí)目標(biāo):

訪問像素值并修改

訪問圖片屬性

設(shè)置圖像區(qū)域(ROI)

拆分、合并圖像

這一節(jié)主要大部分涉及 Numpy 庫的使用

訪問并且修改像素值

import cv2

import numpy as np

# 加載一個(gè)彩色圖

img = cv2.imread("img.jpg")

img.shape

(150, 220, 3)

px = img[100, 100]

print(px)

blue = img[100, 100, 0]

print(blue)

[ 85 180 173]

85

# 修改特定的像素

img[100, 100] = [255, 255, 255]

print(img[100, 100])

# 這種修改每個(gè)像素的做法效率很低

[255 255 255]

最好使用下面這種方法

# 獲取 RED 通道值

img.item(10, 10, 1)

# 修改

img.itemset((10, 10, 2), 100)

img.item(10, 10, 2)

100

顏色空間縮減

若是單通道的像素,像素有 256(0-255)個(gè)值,若是三通道,則顏色數(shù)就更多(一千六百多萬種),如此多的顏色進(jìn)行處理,會(huì)對(duì)算法的性能造成影響。這些顏色中,有代表性的顏色只是小部分。

顏色空間縮減(color space reduction)可以大大降低運(yùn)算復(fù)雜度,具體做法是:

0-9 范圍的像素值為 0;

10-19 范圍像素值為 10;

以此類推

算法實(shí)現(xiàn)步驟:

遍歷圖像矩陣的每個(gè)像素

根據(jù)公式:

img = cv2.imread("img.jpg", 0) # img.shape = 150*220

img_new = np.array([i for i in map(lambda x:(x//10)*10, img)])

cv2.imshow("img", img)

cv2.imshow("img_new", img_new)

cv2.waitKey(0)

cv2.destroyAllWindows()

# 統(tǒng)計(jì)不同元素的個(gè)數(shù)

np.unique(img),np.unique(img_new)

(array([ 21, 26, 28, 33, 34, 35, 37, 38, 39, 40, 41, 42, 43,

44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,

57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,

70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,

83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,

96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108,

109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121,

122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,

135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147,

148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160,

161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,

174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,

187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,

200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212,

213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225,

226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,

239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,

252, 253, 254, 255], dtype=uint8),

array([ 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140,

150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250], dtype=uint8))

運(yùn)行結(jié)果,從肉眼來看,差別不大

image

獲取圖像的屬性

img;

img.shape

# 若是彩色圖像,則返回元組 1*3

# 若是灰色圖像,則返回元組 1*2 只有行和列

# 此方法可以用來判斷是否為彩色圖像

(150, 220)

# 所有像素的總和即上面的元組值相乘

img.size

33000

# 圖像的數(shù)據(jù)類型

img.dtype

dtype('uint8')

img.dtype 在調(diào)試時(shí)非常重要,因?yàn)榇蟛糠皱e(cuò)誤是因?yàn)闊o效的數(shù)據(jù)類型引起的

感興趣區(qū)域(ROI)

該部分的功能是對(duì)圖像的一小部分區(qū)域進(jìn)行處理(我們感興趣的那部分),可以減少處理時(shí)間,增加精度,給圖像處理帶來便利。

img = cv2.imread("messi5.jpg")

cv2.imshow("image_init", img)

ball = img[280:340, 330:390]

img[273:333, 100:160] = ball

cv2.imshow("image_roi", img)

k = cv2.waitKey(0) & 0xFF

if k == 27:

cv2.destroyAllWindows()

本例是對(duì)找到圖像中球的位置,并復(fù)制一個(gè)放在另外一個(gè)地方,注意看的話,你會(huì)發(fā)現(xiàn)復(fù)制的球是一個(gè)矩形,看起來并不協(xié)調(diào)?

image

拆分、合并圖像通道

# 拆分每個(gè)通道

b,g,r = cv2.split(img) # 或者 b = img[:, :, 0]

# 把各個(gè)通道合并起來

img = cv2.merge((b,g,r))

# 讓紅色通道置零,可以不用拆分紅色通道,直接置零

img[:, :, 2] = 0

cv2.split() 對(duì)系統(tǒng)來說開銷很大,所以只在需要使用的時(shí)候再使用,使用 Numpy 索引的方法更有效

為圖像創(chuàng)建邊框(填充)

cv2.copyMakeBorder(): 可以為圖像創(chuàng)建邊框它在 卷積運(yùn)算,零填充等方面有更多的應(yīng)用

import cv2

import numpy as np

from matplotlib import pyplot as plt

BLUE = [255, 0, 0]

img1 = cv2.imread('opencv-logo.png')

replicate = cv2.copyMakeBorder(

img1, 10, 10, 10, 10, cv2.BORDER_REPLICATE) # 最后一個(gè)元素的復(fù)制

reflect = cv2.copyMakeBorder(img1, 10, 10, 10, 10, cv2.BORDER_REFLECT) # 邊框的鏡面

reflect101 = cv2.copyMakeBorder(

img1, 10, 10, 10, 10, cv2.BORDER_REFLECT_101) # 同上,但有細(xì)微變化

wrap = cv2.copyMakeBorder(img1, 10, 10, 10, 10, cv2.BORDER_WRAP)

# 添加一個(gè)固定顏色的邊框,因?yàn)?matpltlib 和 opencv 顏色顯示不一樣,所有圖標(biāo)的紅色和藍(lán)色互換了

constant = cv2.copyMakeBorder(

img1, 10, 10, 10, 10, cv2.BORDER_CONSTANT, value=BLUE)

plt.subplot(231), plt.imshow(img1, 'gray'), plt.title('ORIGINAL')

plt.subplot(232), plt.imshow(replicate, 'gray'), plt.title('REPLICATE')

plt.subplot(233), plt.imshow(reflect, 'gray'), plt.title('REFLECT')

plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.title('REFLECT_101')

plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('WRAP')

plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('CONSTANT')

plt.show()

image

函數(shù)說明

copyMakeBorder(src, top, bottom, left, right, borderType[, dst[, value]]) -> dst

src: 輸入圖片

top, bottom, left, right: 上下左右的寬度

borderType: 邊框類型,多個(gè)可以選擇 參見

更多資料

圖像對(duì)比度、亮度值調(diào)整

學(xué)習(xí)目標(biāo):

用 OpenCV 進(jìn)行圖像對(duì)比度、亮度的動(dòng)態(tài)調(diào)整

理論依據(jù)

一般的圖像處理算子都是一個(gè)函數(shù),它接受一個(gè)或多個(gè)輸入圖像,并產(chǎn)生輸出圖像。算子的一般形式:

或者

圖像亮度和對(duì)比度的調(diào)整操作,屬于圖像操作中的點(diǎn)操作。點(diǎn)操作的特點(diǎn):僅僅根據(jù)輸入像素值(有時(shí)可加上某些全局信息或參數(shù)),來計(jì)算相應(yīng)的輸出像素值。這類算子包括:亮度(brightness)、對(duì)比度(contrast)調(diào)整、顏色校正(colorcorrection)、變換(transformations)。

常見的點(diǎn)操作(或說點(diǎn)算子)是乘上一個(gè)常數(shù)(對(duì)應(yīng)對(duì)比度發(fā)調(diào)節(jié))和加上一個(gè)常數(shù)(對(duì)應(yīng)亮度的調(diào)節(jié))。公式為:

各個(gè)參數(shù)的含義:

參數(shù) f(x) 表示源圖像像素

參數(shù) g(x) 表示輸出圖像像素

參數(shù) a (需要滿足 a>0 )被稱為增益(gain),控制圖像的對(duì)比度

參數(shù) b 稱為偏置(bias),控制圖像的亮度

公式改寫:

即對(duì)圖像的 i 行 j 列的像素進(jìn)行操作。(對(duì)所有的像素進(jìn)行操作)

案例(利用軌跡條調(diào)節(jié)圖像的亮度和對(duì)比度)

import numpy as np

import cv2

from skimage import img_as_int

def nothing(x):

pass

# 對(duì)比度和亮度調(diào)節(jié)函數(shù)

def adjust_bright_contrast(img, a=1, b=0):

new_img = np.zeros(img.shape, dtype=img.dtype)

for b in range(img.shape[0]):

for g in range(img.shape[1]):

for r in range(img.shape[2]):

new_img[b, g, r] = np.clip(a*img[b, g, r]+b, 0, 255)

return new_img

# 使用軌跡條應(yīng)該先創(chuàng)建一個(gè)窗口,因?yàn)?/p>

cv2.namedWindow("image")

cv2.createTrackbar("bright", "image", 0, 300, nothing)

cv2.createTrackbar("contrast", "image", 0, 255, nothing)

img = cv2.imread("img.jpg")

new_img = np.zeros(img.shape, dtype=img.dtype)

while(1):

cv2.imshow("image", new_img)

k = cv2.waitKey(1) & 0xFF

if k == 27:

break

brightness = cv2.getTrackbarPos("bright", "image")

contrast = cv2.getTrackbarPos("contrast", "image")

new_img[:] = adjust_bright_contrast(img, brightness*0.01, contrast)

cv2.destroyAllWindows()

運(yùn)行結(jié)果:

image

這個(gè)方式運(yùn)行起來很慢,因?yàn)槔锩嬗腥龑友h(huán)

離散傅立葉變換

待學(xué)習(xí)

圖像的算術(shù)運(yùn)算

學(xué)習(xí)目標(biāo):

圖像的加法、減法、位運(yùn)算

cv2.add(), cv2.addWeighted()

圖像加法

cv2.add() 使用該函數(shù)操作是 Numpy 操作,兩個(gè)圖片應(yīng)該要有一樣的數(shù)據(jù)類型和深度,否則第二個(gè)圖像只能是標(biāo)量值。

x = np.uint8([250])

y = np.uint8([10])

z = np.uint8([255])

print("opencv add operation:", cv2.add(x, y)) # 250+10 = 260 => 255

print("opencv sub operation:", cv2.subtract(x, z)) # 250-255 = -5 => 0

print("numpy add operation:", x+y) # 250+10 = 260 % 256 = 4

print("numpy sub operation:", x-z) # 250-255 = -5 % 256 = 251

opencv add operation: [[255]]

opencv sub operation: [[0]]

numpy add operation: [4]

numpy sub operation: [251]

OpenCV 運(yùn)算和 Numpy 運(yùn)算有區(qū)別:OpenCV 是飽和運(yùn)算,即相加最大只能是 255 ,相減最小只能是 0。Numpy 是模運(yùn)算。見上面注釋。

最好使用 OpenCV 中的 add 進(jìn)行運(yùn)算

圖像融合

cv2.addWeighted() 兩張圖片以權(quán)重進(jìn)行融合,使其給人一種混合或透明的感覺。圖片按以下公式運(yùn)算

img1 = cv2.imread("ml.png")

img2 = cv2.imread("opencv-logo.png")

dst = cv2.addWeighted(img1, 0.7, img2, 0.3, 0)

cv2.imshow('dst', dst)

cv2.waitKey(0)

cv2.destroyAllWindows()

addWeighted 運(yùn)算公式為:

image

軌跡條版本

img1 = cv2.imread("ml.png")

img2 = cv2.imread("opencv-logo.png")

def nothing(x):

pass

cv2.namedWindow("image")

cv2.createTrackbar("alpha", "image", 0, 100, nothing)

dst = np.zeros(img1.shape, dtype=img1.dtype)

while(1):

cv2.imshow('image', dst)

alpha = cv2.getTrackbarPos("alpha", "image")

dst = cv2.addWeighted(img1, alpha*0.01, img2, 1 -alpha*0.01, 0)

k = cv2.waitKey(1) & 0xFF

if k == 27:

break

cv2.destroyAllWindows()

位運(yùn)算

包括 AND、OR、NOT 和 XOR 操作。它們?cè)谔崛D像的任何部分、定義和處理非矩形 ROI 時(shí)非常有用。

AND 運(yùn)算

# 畫矩形

Rectangle = np.zeros((300, 300), dtype="uint8")

cv2.rectangle(Rectangle, (25, 25), (275, 275), 255, -1)

cv2.imshow("Rectangle", Rectangle)

cv2.waitKey(0)

# 畫圓形

Circle = np.zeros((300, 300), dtype="uint8")

cv2.circle(Circle, (150, 150), 150, 255, -1)

cv2.imshow("Circle", Circle)

cv2.waitKey(0)

bit_and = cv2.bitwise_and(Rectangle, Circle)

cv2.imshow("bit_and", bit_and)

cv2.waitKey(0)

"""

sub = cv2.subtract(Rectangle, Circle)

cv2.imshow("sub", sub)

cv2.waitKey()

"""

cv2.destroyAllWindows()

x = np.uint8([10])

y = np.uint8([20])

z = np.uint8([10])

cv2.bitwise_and(x, y), cv2.bitwise_and(x, z)

(array([[0]], dtype=uint8), array([[10]], dtype=uint8))

運(yùn)行結(jié)果

image

OR 運(yùn)算

# 畫矩形

Rectangle = np.zeros((300, 300), dtype="uint8")

cv2.rectangle(Rectangle, (25, 25), (275, 275), 255, -1)

cv2.imshow("Rectangle", Rectangle)

cv2.waitKey(0)

# 畫圓形

Circle = np.zeros((300, 300), dtype="uint8")

cv2.circle(Circle, (150, 150), 150, 255, -1)

cv2.imshow("Circle", Circle)

cv2.waitKey(0)

bit_or = cv2.bitwise_or(Rectangle, Circle)

cv2.imshow("bit_or", bit_or)

cv2.waitKey(0)

add = cv2.add(Rectangle, Circle)

cv2.imshow("add", add)

cv2.waitKey(0)

cv2.destroyAllWindows()

x = np.uint8([10]) # 0000 1010

y = np.uint8([20]) # 0001 0100

z = np.uint8([40]) # 0010 1000

print(cv2.bitwise_or(x, y)) # 0001 1110 => 30

print(cv2.bitwise_or(x, z)) # 0010 1010 => 42

[[30]]

[[42]]

OR 運(yùn)算和 cv2.add() 結(jié)果一致?

運(yùn)行結(jié)果

image

XOR(異或)運(yùn)算

# 畫矩形

Rectangle = np.zeros((300, 300), dtype="uint8")

cv2.rectangle(Rectangle, (25, 25), (275, 275), 255, -1)

cv2.imshow("Rectangle", Rectangle)

cv2.waitKey(0)

# 畫圓形

Circle = np.zeros((300, 300), dtype="uint8")

cv2.circle(Circle, (150, 150), 150, 255, -1)

cv2.imshow("Circle", Circle)

cv2.waitKey(0)

bit_xor = cv2.bitwise_xor(Rectangle, Circle)

cv2.imshow("bit_xor", bit_xor)

cv2.waitKey(0)

cv2.destroyAllWindows()

運(yùn)行結(jié)果

image

NOT 運(yùn)算

# 畫矩形

Rectangle = np.zeros((300, 300), dtype="uint8")

cv2.rectangle(Rectangle, (25, 25), (275, 275), 255, -1)

cv2.imshow("Rectangle", Rectangle)

cv2.waitKey(0)

# 畫圓形

Circle = np.zeros((300, 300), dtype="uint8")

cv2.circle(Circle, (150, 150), 150, 255, -1)

cv2.imshow("Circle", Circle)

cv2.waitKey(0)

bit_not = cv2.bitwise_not(Rectangle, Circle)

cv2.imshow("bit_not", bit_not)

cv2.waitKey(0)

cv2.destroyAllWindows()

運(yùn)行結(jié)果

image

綜合例程

mask:圖像掩模

# 加載圖片

img1 = cv2.imread("messi5.jpg")

img2 = cv2.imread("opencv-logo.png")

print(img1.shape, img2.shape)

# 把 OpenCV logo 放在圖片的左上角,創(chuàng)建一個(gè) ROI 大小和 logo 圖像一致

rows, cols, channels = img2.shape

roi = img1[0:rows, 0:cols]

print("roi.shape:", roi.shape)

cv2.imshow("roi", roi)

cv2.waitKey(0)

# 灰度圖

img2gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

cv2.imshow("img2gray", img2gray)

cv2.waitKey(0)

ret, mask = cv2.threshold(img2gray, 25, 255, cv2.THRESH_BINARY)

# 解釋:若圖片 im2gray 的像素值小于 25,則像素置 0(黑),否則置 255(白)

# ret :得到的閾值,mask:閾值化后的圖像

print("ret", ret)

cv2.imshow("mask", mask)

cv2.waitKey(0)

mask_inv = cv2.bitwise_not(mask)

# 把 mask 圖像的白色像素變?yōu)楹谏?#xff0c;黑色像素變?yōu)榘咨?/p>

cv2.imshow("mask_inv", mask_inv)

cv2.waitKey(0)

# 將 img1 中的 ROI 的 logo 區(qū)域涂黑

img1_bg = cv2.bitwise_and(roi, roi, mask=mask_inv)

cv2.imshow("img1_bg", img1_bg)

cv2.waitKey(0)

# plt.imshow(img1_bg)

# 只提取 logo 圖像中的 logo

img2_fg = cv2.bitwise_and(img2, img2, mask=mask)

cv2.imshow("img2_fg", img2_fg)

cv2.waitKey(0)

# 將 ROI 區(qū)域與 logo 圖標(biāo)運(yùn)算

dst = cv2.add(img1_bg, img2_fg)

cv2.imshow("dst", dst)

cv2.waitKey(0)

img1[0:rows, 0:cols] = dst

cv2.imshow("res", img1)

cv2.waitKey(0)

cv2.destroyAllWindows()

(342, 548, 3) (186, 152, 3)

roi.shape: (186, 152, 3)

ret 25.0

運(yùn)行結(jié)果

image

要將兩張圖放在一起,且都是原來的圖像,如上圖所示,將 OpenCV logo (img2)放在 img1 上面,巧妙的利用黑色像素(0)。

如何將兩個(gè)圖一原來的圖像進(jìn)行重疊:

創(chuàng)建一個(gè) ROI 區(qū)域(ROI 區(qū)域來自底圖,如上面的例子的 img1)

將 logo 之外的像素置 0 (就是背景是純黑色),如上圖的 img2_fg

將 ROI 區(qū)域上要放置 logo 的位置置 0,如上圖的 img1_bg

將 2、3 步得到的圖像相加( cv2.add() )

將第 4 步得到的圖像將 img1 的區(qū)域替換掉

練習(xí)(用函數(shù)實(shí)現(xiàn)圖像的無縫拼接)

def pinjie(img1, img2, x=0, y=0):

"""

img1: 底圖

img2: 上方的圖

x, y:選擇放置的位置

"""

# 創(chuàng)建一個(gè) ROI

rows, cols, channel = img2.shape

roi = img1[x:x+rows, y:y+cols]

img2gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

ret, mask = cv2.threshold(img2gray, 25, 255, cv2.THRESH_BINARY)

mask_inv = cv2.bitwise_not(mask)

roi = cv2.bitwise_and(roi, roi, mask=mask_inv)

img2_bg = cv2.bitwise_and(img2, img2, mask=mask)

img1[x:x+rows, y:y+cols] = cv2.add(roi, img2_bg)

return img1

img1 = cv2.imread("messi5.jpg")

img2 = cv2.imread("opencv-logo.png")

dst = pinjie(img1, img2, 100, 100)

cv2.imshow("dst", dst)

cv2.waitKey(0)

cv2.destroyAllWindows()

更多資料

性能評(píng)估和改進(jìn)技術(shù)

圖像處理中,不僅需要準(zhǔn)確,更需要快速的方法進(jìn)行處理。

學(xué)習(xí)目標(biāo):

評(píng)估代碼的性能

提升代碼性能的小技巧

cv2.getTickCount, cv2.getTickFrequency

time 模塊可以測(cè)量執(zhí)行時(shí)間;

profile 模塊有助于獲得關(guān)于代碼的詳細(xì)報(bào)告,比如代碼中每個(gè)函數(shù)花費(fèi)了多少時(shí)間、調(diào)用了多少次等等。

使用 OpenCV 衡量性能

cv2.getTickCount 在代碼前后使用可以得到代碼的運(yùn)行時(shí)間

cv2.getTickFrequency 返回時(shí)鐘周期的頻率,即每秒的時(shí)鐘周期數(shù)

img1 = cv2.imread('messi5.jpg')

e1 = cv2.getTickCount()

for i in range(5,49,2):

img1 = cv2.medianBlur(img1,i)

e2 = cv2.getTickCount()

t = (e2 - e1)/cv2.getTickFrequency()

e2 - e1, t

(8315303, 0.8315303)

python 中的 time 模塊也可以實(shí)現(xiàn)該功能

OpenCV 中的默認(rèn)優(yōu)化

OpenCV 的許多函數(shù)都是使用SSE2、AVX等優(yōu)化的。它還包含未優(yōu)化的代碼。因此,如果我們的系統(tǒng)支持這些特性,我們應(yīng)該利用它們(幾乎所有現(xiàn)代處理器都支持它們)。它在編譯時(shí)默認(rèn)啟用。OpenCV 在啟用時(shí)運(yùn)行優(yōu)化后的代碼,否則運(yùn)行未優(yōu)化的代碼。使用 cv2.useoptimization()來檢查它是否啟用/禁用,使用

cv2.setuseoptimization()來啟用/禁用它。

# 檢查優(yōu)化器是否開啟

cv2.setUseOptimized(True)

cv2.useOptimized()

True

img = cv2.imread("messi5.jpg")

%timeit res = cv2.medianBlur(img,49)

31.8 ms ± 1.28 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

# 設(shè)置優(yōu)化器的開關(guān)

cv2.setUseOptimized(False)

cv2.useOptimized()

False

%timeit res = cv2.medianBlur(img,49)

30.9 ms ± 448 μs per loop (mean ± std. dev. of 7 runs, 10 loops each)

可以看出使用優(yōu)化器前后的運(yùn)行性能

IPython 性能測(cè)試

測(cè)試一下下面幾個(gè)計(jì)算平方的方法哪個(gè)更好。

例子:

x = 5; y = x**2、x = 5; y = x*x、x = np.uint8([5]); y = x*x、y = np.square(x) 可以使用 %timeit 進(jìn)行測(cè)試

x = 5

%timeit y = x**2

505 ns ± 18 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%timeit y = x*x

77.5 ns ± 1.98 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

z = np.uint8([5])

%timeit y=z*z

709 ns ± 57.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%timeit y=np.square(z)

674 ns ± 66.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

y = x*x 比 Numpy 運(yùn)算快不少

Python 標(biāo)量操作比 Numpy 標(biāo)量操作快。因此對(duì)于包含一個(gè)或兩個(gè)元素的操作,Python 標(biāo)量?jī)?yōu)于 Numpy 數(shù)組。當(dāng)數(shù)組的大小稍微大一點(diǎn)時(shí),Numpy 就更有優(yōu)勢(shì)。

# 比較 cv2.countNonZero() 和 np.count_nonzero() 的性能

%timeit z = cv2.countNonZero(img[:,:, 0]) # 該函數(shù)只能計(jì)算單通道的圖片

269 μs ± 30.7 μs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit z = np.count_nonzero(img[:,:, 0])

677 μs ± 54.5 μs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

性能優(yōu)化技術(shù)

首先嘗試以一種簡(jiǎn)單的方式實(shí)現(xiàn)該算法。一旦開始工作,對(duì)其進(jìn)行分析,找到瓶頸并對(duì)其進(jìn)行優(yōu)化。

盡量避免循環(huán),特別是 2/3 重的循環(huán)

最大限度地向量化算法/代碼,因?yàn)?Numpy 和 OpenCV 是針對(duì)向量操作進(jìn)行優(yōu)化的。

利用緩存一致性

除非必要,不然盡量不要對(duì)數(shù)組進(jìn)行復(fù)制,數(shù)組復(fù)制的開銷很大

即使在執(zhí)行了所有這些操作之后,如果代碼仍然很慢,或者不可避免地要使用大型循環(huán),那么可以使用其他庫,比如Cython來加快速度。

更多資料

總結(jié)

以上是生活随笔為你收集整理的python 图像无缝拼接,OpenCV Python 系列教程3 - Core 组件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。