一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Python OpenCV #3

 羊玉wngbx 2024-07-07

一、圖像的基本操作

1.1 目標

學(xué)會:

  • 訪問像素值并修改它們
  • 訪問圖像屬性
  • 設(shè)置ROI
  • 分割和合并圖像

本節(jié)中幾乎所有的操作都主要與Numpy而不是OpenCV相關(guān)。要使用OpenCV編寫更好的優(yōu)化代碼,需要對Numpy有很好的了解。

(示例將在Python終端中顯示,因為它們中的大多數(shù)只是單行代碼)

1.2 縮放和修改像素值

下載代碼:點擊 這里

讓我們先加載一個彩色圖像:

>>> import numpy as np
>>> import cv2 as cv
 
>>> img = cv.imread('Ronaldo.png')
>>> assert img is not None, "文件無法讀取,使用os.path.exists()檢查"

可以通過像素的行和列坐標來訪問像素值。對于BGR圖像,它返回一個藍色、綠色和紅色值的數(shù)組。對于灰度圖像,僅返回相應(yīng)的強度。

>>> px = img[100, 100]
>>> print(px)
[25 26 22]
 
# 僅訪問藍色像素
>>> blue = img[100, 100, 0]
>>> print(blue)
25

您可以用同樣的方法修改像素值。

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

警告:

Numpy是一個用于快速數(shù)組計算的優(yōu)化庫。因此,簡單地訪問每個像素值并修改它將非常緩慢,并且不鼓勵。

注意:

上面的方法通常用于選擇數(shù)組的一個區(qū)域,比如前5行和后3列。對于單個像素訪問,Numpy數(shù)組方法array.item()和array.itemset()被認為是更好的。

它們總是返回一個標量,但是,如果你想訪問所有的B、G、R值,你需要為每個值分別調(diào)用array.item()。

更好的像素訪問和編輯方法:

# 訪問RED值
>>> img.item(10, 10, 2)
34
 
# 修改RED值
>>> img.itemset((10, 10, 2), 100)
>>> img.item(10, 10, 2)
100

1.3 圖像屬性

下載代碼:點擊 這里

加載另一個彩色圖像:

>>> import numpy as np
>>> import cv2 as cv
 
>>> img = cv.imread('Ronaldo2.jpg')
>>> assert img is not None, "文件無法讀取,使用os.path.exists()檢查"

圖像屬性包括行數(shù)、列數(shù)和通道數(shù);圖像數(shù)據(jù)類型;像素數(shù)等。

圖像的形狀通過img.shape訪問。它返回一個包含行數(shù)、列數(shù)和通道數(shù)的元組(如果圖像是彩色的):

>>> print(img.shape)
(423, 634, 3)

注意:

如果圖像是灰度的,返回的元組只包含行數(shù)和列數(shù),因此這是檢查加載的圖像是灰度還是彩色的好方法。

img.size訪問的像素總數(shù):

>>> print(img.size)
804546

圖像數(shù)據(jù)類型通過img.dtype獲?。?/p>

>>> print(img.dtype)
uint8

注意:

img.dtype在調(diào)試時非常重要,因為OpenCV-Python代碼中的大量錯誤都是由無效的數(shù)據(jù)類型引起的。

1.4 圖像和ROI

下載代碼:點擊 這里

有時,您需要對圖像的某些區(qū)域進行檢測。在圖像中檢測眼睛時,首先要對整個圖像進行人臉檢測。獲得人臉后,我們只選擇人臉區(qū)域,然后在該區(qū)域內(nèi)搜索眼睛,而不是搜索整個圖像。

它提高了準確性,因為眼睛總是在臉上 ?? 和性能(因為我們在一個小區(qū)域內(nèi)搜索)。

ROI再次使用Numpy索引獲得。在這里,我選擇了Ronaldo的膝蓋部分,并將其復(fù)制到圖像中的另一個區(qū)域:

>>> ball = img[298:354, 366:418]
>>> img[148:360, 216:424] = ball

查看如下結(jié)果:

Python OpenCV #3 - 核心操作_python

1.5 分割和合并圖像通道

有時您需要分別處理圖像的B、G、R通道。在這種情況下,您需要將BGR圖像拆分為單個通道。在其他情況下,您可能需要連接這些單獨的通道以創(chuàng)建BGR映像。您可以通過以下方式簡單地做到這一點:

>>> b, g, r = cv.split(img)
>>> img = cv.merge((b, g, r))

或者

>>> b = img[:, :, 0]

假設(shè)您要將所有紅色像素設(shè)置為零——您不需要首先拆分通道。Numpy索引更快:

>>> img[:, :, 2] = 0

警告:

cv.split()是一個代價很高的操作(就時間而言)。所以只在必要時使用它,否則就用Numpy索引。

1.6 為圖像制作邊框(填充)

下載代碼:點擊 這里

如果您想在圖像周圍創(chuàng)建一個邊框,比如一個相框,您可以使用cv.copyMakeBorder()。但它有更多的卷積運算,零填充等應(yīng)用程序。此函數(shù)采用以下參數(shù):

  • src :輸入圖像
  • top, bottom, left, right :相應(yīng)方向上的像素數(shù)的邊框?qū)挾?/li>
  • borderType :定義要添加的邊框類型的標志。它可以是以下類型:
    • cv.BORDER_CONSTANT - 添加一個恒定顏色的邊框。該值應(yīng)作為下一個參數(shù)給出。
    • cv.BORDER_REFLECT - Border將是邊框元素的鏡像反射,如下所示: fedcba|abcdefgh|hgfedcb
    • cv.BORDER_REFLECT_101cv.BORDER_DEFAULT - 與上述相同,但略有變化,如下所示: gfedcb|abcdefgh|gfedcba
    • cv.BORDER_REPLICATE - 最后一個元素被復(fù)制,如下所示: aaaaaa|abcdefgh|hhhhhhh
    • cv.BORDER_WRAP - 無法解釋,它看起來像這樣: cdefgh|abcdefgh|abcdefg
  • value :如果邊框類型為cv.BORDER_CONSTANT,則邊框的顏色

下面是一個示例代碼,演示了所有這些邊框類型,以便更好地理解:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
 
BLUE = [255, 0, 0]
 
img1 = cv.imread('opencv-logo.png')
assert img1 is not None,  "文件無法讀取,使用os.path.exists()檢查"
 
replicate = cv.copyMakeBorder(img1, 10, 10, 10, 10, cv.BORDER_REPLICATE)
reflect = cv.copyMakeBorder(img1, 10, 10, 10, 10, cv.BORDER_REFLECT)
reflect101 = cv.copyMakeBorder(img1, 10, 10, 10, 10, cv.BORDER_REFLECT_101)
wrap = cv.copyMakeBorder(img1, 10, 10, 10, 10, cv.BORDER_WRAP)
constant= cv.copyMakeBorder(img1, 10, 10, 10, 10, cv.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()

請參見下面的結(jié)果。(圖像是用matplotlib顯示的。因此,紅色和藍色通道將互換):

Python OpenCV #3 - 核心操作_OpenCV_02

二、圖像的算術(shù)運算

2.1 目標

  • 學(xué)習(xí)圖像上的幾種算術(shù)運算,如加法,減法,按位運算等。
  • 學(xué)習(xí)這些函數(shù):cv.add()cv.addWeighted()等。

2.2 圖像疊加

下載代碼:點擊 這里

您可以使用OpenCV函數(shù)cv.add()添加兩個圖像,或者簡單地使用numpy操作res = img1 + img2。兩個圖像應(yīng)該具有相同的深度和類型,或者第二個圖像可以只是一個標量值。

注意:

OpenCV加法和Numpy加法之間有區(qū)別。OpenCV加法是飽和運算,而Numpy加法是模運算。

例如,請看下面的示例:

>>> x = np.uint8([250])
>>> y = np.uint8([10])
 
>>> print(cv.add(x, y)) # 250+10 = 260 => 255
[[260.]
 [  0.]
 [  0.]
 [  0.]]
 
>>> print(x+y) # 250+10 = 260 % 256 = 4
[4]

當你添加兩個圖像時,這將更加明顯。堅持使用OpenCV函數(shù),因為它們會提供更好的結(jié)果。

2.3 圖像混合

下載代碼:點擊 這里

這也是圖像相加,但不同的權(quán)重被賦予圖像,以給出混合或透明的感覺。按照以下公式添加圖像:

g(x)=(1?α)f0(x)+αf1(x)

通過改變α的值(01),您可以在一個圖像到另一個圖像之間執(zhí)行很酷的過渡。

在這里,我把兩個圖像融合在一起。第一個圖像的權(quán)重為0.7,第二個圖像的權(quán)重為0.3。cv.addWeighted()將以下等式應(yīng)用于圖像:

dst=α?img1+β?img2+γ

這里γ取0。

import numpy as np
import cv2 as cv

img1 = cv.imread('ml.jpg')
img2 = cv.imread('opencv-logo2.png')
assert img1 is not None,  "文件無法讀取,使用os.path.exists()檢查"
assert img2 is not None,  "文件無法讀取,使用os.path.exists()檢查"
 
dst = cv.addWeighted(img1, 0.7, img2, 0.3, 0)
 
cv.imshow('dst', dst)
cv.waitKey(0)
cv.destroyAllWindows()

請看下面的結(jié)果:

Python OpenCV #3 - 核心操作_.net_03

2.4 按位運算

下載代碼:點擊 這里

這包括按位AND、OR、NOT和XOR運算。在提取圖像的任何部分(我們將在接下來的章節(jié)中看到),定義和處理非矩形ROI等時,它們都非常有用。

下面我們將看到一個如何改變圖像特定區(qū)域的示例。

我想把OpenCV徽標放在圖像上方。如果我添加兩個圖像,它會改變顏色。如果我混合它們,我會得到透明的效果。但我希望它不透明。如果它是一個矩形區(qū)域,我可以像上一章那樣使用ROI。

但是OpenCV的標志不是矩形的。所以你可以用按位操作來做,如下所示:

import numpy as np
import cv2 as cv

# 加載兩個圖片
img1 = cv.imread('Ronaldo3.png')
img2 = cv.imread('opencv-logo2.png')
assert img1 is not None, "文件無法讀取,使用os.path.exists()檢查"
assert img2 is not None, "文件無法讀取,使用os.path.exists()檢查"
 
# 我想把標志放在左上角,所以我創(chuàng)建ROI
rows, cols, channels = img2.shape
roi = img1[0:rows, 0:cols]
 
# 現(xiàn)在創(chuàng)建一個logo蒙版,同時創(chuàng)建其反向蒙版
img2gray = cv.cvtColor(img2, cv.COLOR_BGR2GRAY)
ret, mask = cv.threshold(img2gray, 10, 255, cv.THRESH_BINARY)
mask_inv = cv.bitwise_not(mask)
 
# 現(xiàn)在涂黑ROI中的logo區(qū)域
img1_bg = cv.bitwise_and(roi, roi, mask=mask_inv)
 
# 從logo圖像中只提取logo區(qū)域。
img2_fg = cv.bitwise_and(img2, img2, mask=mask)
 
# 在ROI中加入logo并修改主圖像
dst = cv.add(img1_bg, img2_fg)
img1[0:rows, 0:cols] = dst
 
cv.imshow('res', img1)
cv.waitKey(0)
cv.destroyAllWindows()

請看下面的結(jié)果。左圖顯示了我們創(chuàng)建的掩碼。右圖顯示最終結(jié)果。為了更好地理解,顯示上面代碼中的所有中間圖像,特別是img1_bg和img2_fg。

Python OpenCV #3 - 核心操作_python_04

2.5 額外資源

2.5.1 練習(xí)

  1. 使用cv.addWeighted函數(shù)創(chuàng)建文件夾中圖像的幻燈片放映,圖像之間平滑過渡

三、效能衡量和改進技術(shù)

3.1 目標

在圖像處理中,由于每秒要處理大量操作,因此代碼不僅要提供正確的解決方案,還要以最快的速度提供解決方案。因此,在本章中,你將學(xué)習(xí)

  • 衡量代碼性能。
  • 提高代碼性能的一些技巧。
  • 您將看到這些函數(shù):cv.getTickCount、cv.getTickFrequency等。

除了OpenCV,Python還提供了一個模塊 time ,這有助于測量執(zhí)行時間。另一個模塊 profile 有助于獲得關(guān)于代碼的詳細報告,例如代碼中每個函數(shù)花費了多少時間,函數(shù)被調(diào)用了多少次等。但是,如果您使用IPython,所有這些功能都以用戶友好的方式集成。

我們將看到一些重要的,更多的細節(jié),請查看本節(jié)的“額外資源”。

3.2 使用OpenCV衡量性能

下載代碼:點擊 這里

函數(shù)cv.getTickCount返回從參考事件(如機器打開的時刻)到調(diào)用該函數(shù)的時刻的時鐘周期數(shù)。因此,如果你在函數(shù)執(zhí)行之前和之后調(diào)用它,你會得到用于執(zhí)行函數(shù)的時鐘周期數(shù)。

cv.getTickFrequency函數(shù)返回時鐘周期的頻率,或每秒時鐘周期的數(shù)量。因此,要查找以秒為單位的執(zhí)行時間,您可以執(zhí)行以下操作:

e1 = cv.getTickCount()
# 你的代碼操作
e2 = cv.getTickCount()
time = (e2 - e1) / cv.getTickFrequency()

我們將通過下面的示例進行演示。下面的示例使用中值濾波,其內(nèi)核大小為奇數(shù),從5到49不等(不用擔心結(jié)果會是什么樣子——那不是我們的目標):

img1 = cv.imread('Ronaldo.png')
assert img1 is not None, "文件無法讀取,使用os.path.exists()檢查"
 
e1 = cv.getTickCount()
for i in range(5, 49, 2):
    img1 = cv.medianBlur(img1, i)
e2 = cv.getTickCount()
t = (e2 - e1) / cv.getTickFrequency()
print(t)
 
# 我得到的結(jié)果是 0.8226811s

注意:

你可以用time模塊做同樣的事情。使用time.time()函數(shù)代替cv.getTickCount。然后取兩次的差。

3.3 OpenCV中的默認優(yōu)化

OpenCV的許多函數(shù)都使用SSE2,AVX等進行了優(yōu)化,它還包含未優(yōu)化的代碼。因此,如果我們的系統(tǒng)支持這些功能,我們應(yīng)該利用它們(幾乎所有現(xiàn)代處理器都支持它們)。在編譯時默認啟用它。

因此,如果啟用了OpenCV,它將運行優(yōu)化的代碼,否則將運行未優(yōu)化的代碼。你可以使用cv.useOptimized()來檢查它是否被啟用/禁用,使用cv. setupOptimized()來啟用/禁用它。讓我們看一個簡單的例子。

# 檢查是否啟用了優(yōu)化
In [5]: cv.useOptimized()
Out[5]: True
 
In [6]: %timeit res = cv.medianBlur(img,49)
10 loops, best of 3: 34.9 ms per loop
 
# 禁用它
In [7]: cv.setUseOptimized(False)
 
In [8]: cv.useOptimized()
Out[8]: False
 
In [9]: %timeit res = cv.medianBlur(img,49)
10 loops, best of 3: 64.1 ms per loop

可以看出,優(yōu)化后的中值濾波比未優(yōu)化的版本快2倍。如果查看其源代碼,可以發(fā)現(xiàn)中值濾波是經(jīng)過 SIMD 優(yōu)化的。因此,你可以利用這一點在代碼頂部啟用優(yōu)化(記住,默認情況下是啟用的)。

3.4 在IPython中測量性能

有時您可能需要比較兩個類似操作的性能。IPython提供了一個神奇的命令timeit來執(zhí)行此操作。它多次運行代碼以獲得更準確的結(jié)果。同樣,它適用于測量單行代碼。

例如,你知道下面哪種加法運算更好:

x = 5
y = x**2
x = 5
y = x * x
x = np.uint8([5])
y = x * x

還是

x = np.uint8([5])
y = np.square(x)

我們將在IPython shell中使用timeit進行驗證。

In [10]: x = 5
 
In [11]: %timeit y = x ** 2
10000000 loops, best of 3: 73 ns per loop
 
In [12]: %timeit y = x * x
10000000 loops, best of 3: 58.3 ns per loop
 
In [15]: z = np.uint8([5])
 
In [17]: %timeit y = z * z
1000000 loops, best of 3: 1.25 us per loop
 
In [19]: %timeit y  \= np.square(z)
1000000 loops, best of 3: 1.16 us per loop

你可以看到,第二種是最快的,它比Numpy快了20倍左右。如果您還考慮陣列創(chuàng)建,它可能會快100倍。很酷吧 (Numpy開發(fā)人員正在處理這個問題)

注意:

Python標量操作比Numpy標量操作更快。因此,對于包含一個或兩個元素的操作,Python標量優(yōu)于Numpy數(shù)組。當數(shù)組的大小稍微大一點時,Numpy具有優(yōu)勢。

我們再舉一個例子。這一次,我們將比較cv.countNonZero()np.count_nonzero()對同一圖像的性能。

In [35]: %timeit z = cv.countNonZero(img)
100000 loops, best of 3: 15.8 us per loop
 
In [36]: %timeit z = np.count_nonzero(img)
1000 loops, best of 3: 370 us per loop

看,OpenCV函數(shù)比Numpy函數(shù)快了近25倍。

3.5 更多IPython神奇命令

還有其他幾個神奇的命令來測量性能,分析,行分析,內(nèi)存測量等,他們都是有據(jù)可查的。所以這里只提供這些文檔的鏈接。有興趣的讀者可以嘗試一下(參見“額外資源”)。

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

有幾種技術(shù)和編碼方法可以利用Python和Numpy的最大性能。這里只提到相關(guān)的,并提供重要來源的鏈接。這里要注意的主要事情是,首先嘗試以簡單的方式實現(xiàn)算法。

一旦它開始工作,分析它,找到瓶頸,并優(yōu)化它們。

  1. 盡可能避免在Python中使用循環(huán),尤其是雙循環(huán)、三循環(huán)等,它們天生就很慢。
  2. 盡可能最大程度地對算法、代碼進行矢量化,因為Numpy和OpenCV針對矢量操作進行了優(yōu)化。
  3. 利用緩存一致性。
  4. 除非必要,否則不要復(fù)制數(shù)組。嘗試使用視圖代替。數(shù)組復(fù)制是一項成本高昂的操作。

3.7 額外資源

  1.  Python優(yōu)化技術(shù)
  2.  Scipy講座筆記-高級Numpy
  3.  IPython中的計時和分析

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    福利专区 久久精品午夜| 国产又黄又猛又粗又爽的片| 国产91麻豆精品成人区| 大尺度激情福利视频在线观看| 丁香七月啪啪激情综合| 国产女优视频一区二区| 欧美日韩综合免费视频| 欧美日韩亚洲巨色人妻| 欧美日韩国产免费看黄片| 日本道播放一区二区三区| 欧美亚洲91在线视频| 日韩性生活片免费观看| 欧美一级内射一色桃子| 国产亚洲精品久久久优势| 国产亚洲精品俞拍视频福利区| 五月天婷亚洲天婷综合网| 福利在线午夜绝顶三级| 黑鬼糟蹋少妇资源在线观看| 日韩欧美综合在线播放| 久久99热成人网不卡| 婷婷色香五月综合激激情| 久久综合亚洲精品蜜桃| 91一区国产中文字幕| 狠狠干狠狠操亚洲综合| 久草视频这里只是精品| 国产视频一区二区三区四区| 国产高清一区二区白浆| 丝袜视频日本成人午夜视频 | 不卡视频在线一区二区三区| 日本久久中文字幕免费| 男人大臿蕉香蕉大视频| 精品人妻少妇二区三区| 人妻久久一区二区三区精品99| 国产传媒免费观看视频| 久热99中文字幕视频在线| 国产精品不卡免费视频| 日韩精品一级一区二区| 又黄又硬又爽又色的视频 | 在线免费视频你懂的观看| 日韩免费国产91在线| 日本欧美视频在线观看免费|