久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Python OpenCV #3

 羊玉wngbx 2024-07-07

一,、圖像的基本操作

1.1 目標(biāo)

學(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()檢查"

可以通過像素的行和列坐標(biāo)來訪問像素值,。對于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()被認(rèn)為是更好的。

它們總是返回一個標(biāo)量,,但是,,如果你想訪問所有的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)搜索眼睛,,而不是搜索整個圖像,。

它提高了準(zhǔn)確性,因為眼睛總是在臉上 ?? 和性能(因為我們在一個小區(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 :定義要添加的邊框類型的標(biāo)志,。它可以是以下類型:
    • 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 目標(biāo)

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

2.2 圖像疊加

下載代碼:點擊 這里

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

注意:

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]

當(dāng)你添加兩個圖像時,,這將更加明顯。堅持使用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徽標(biāo)放在圖像上方。如果我添加兩個圖像,,它會改變顏色,。如果我混合它們,我會得到透明的效果,。但我希望它不透明,。如果它是一個矩形區(qū)域,我可以像上一章那樣使用ROI,。

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

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()檢查"
 
# 我想把標(biāo)志放在左上角,所以我創(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 目標(biāo)

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

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

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

我們將看到一些重要的,,更多的細(xì)節(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不等(不用擔(dān)心結(jié)果會是什么樣子——那不是我們的目標(biāo)):

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中的默認(rèn)優(yōu)化

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

3.4 在IPython中測量性能

有時您可能需要比較兩個類似操作的性能,。IPython提供了一個神奇的命令timeit來執(zhí)行此操作。它多次運行代碼以獲得更準(zhǔn)確的結(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標(biāo)量操作比Numpy標(biāo)量操作更快。因此,,對于包含一個或兩個元素的操作,,Python標(biāo)量優(yōu)于Numpy數(shù)組。當(dāng)數(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)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多