<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          獨家|OpenCV 1.2 如何用OpenCV掃描圖像、查找表和測量時間(附鏈接)

          共 4773字,需瀏覽 10分鐘

           ·

          2021-07-30 23:38

          翻譯:陳之炎

          校對:張一然、林夕


          本文約4400字,建議閱讀10分鐘

          本文為大家系統(tǒng)地介紹了OpenCV官方教程。


          目標(biāo)


          在這里將尋求以下問題的答案:

          • 如何遍歷圖像的各個像素?

          • OpenCV的矩陣值是如何存儲的?

          • 如何衡量算法的性能?

          • 什么是查找表,為什么要使用查找表?


          測試案例


          首先來考慮一個簡單的減色方法。利用C和C ++的無符號字符(unsigned char)數(shù)據(jù)類型來存儲矩陣項,像素的一個通道可以具備256個不同的值。對于一幅三通道的圖像來說,可以構(gòu)造出多種色彩(色彩數(shù)量可達(dá)16,000,000種)。數(shù)量眾多的顏色會給算法的性能帶來沉重的負(fù)擔(dān)。然而,有些時候,往往利用較少的色彩數(shù)便能夠獲得同樣的結(jié)果。

          在這種情況下,常見的做法是減少色彩空間(color space reduction)。這意味著,將色彩空間的當(dāng)前值除以一個新的輸入值,從而減少顏色的數(shù)量。例如:將零和九之間的每一個值設(shè)置為零,十和十九之間的值設(shè)置為十等等。

          當(dāng)一個UCHAR 值(無符號字符unsigned char -0到255之間的值)除以INT值之后,其結(jié)果也將是一個數(shù)據(jù)類型為char的值,并且相除之后的結(jié)果值只能為char數(shù)據(jù)類型的值,小數(shù)部分將被舍去。利用C和C ++的這一優(yōu)勢,對 UCHAR域的操作可以表示為:

          簡單的減色算法將該公式應(yīng)用于圖像矩陣中的每個像素,值得一提的是:我們進(jìn)行了一次除法和一次乘法運(yùn)算,這兩種運(yùn)算會耗費昂貴的系統(tǒng)開銷。如果可能的話,可以用一些開銷相對來說比較小的操作來取代它們,如一些減法, 加法或者一些簡單的賦值運(yùn)算操作。此外,需要注意的是,上述操作的輸入值的數(shù)量是有限的,對于UCHAR數(shù)據(jù)類型,準(zhǔn)確地來講,輸入值的數(shù)量為256。

          對于較大的圖像,則是通過使用查找表,將事先計算好所有可能的值在賦值階段直接進(jìn)行賦值操作。查找表是具有一個或多個維度的簡單數(shù)組,對于給定的輸入值對應(yīng)一個確定的輸出值。它的優(yōu)勢在于:無需進(jìn)行計算,便能讀取到結(jié)果。

          測試?yán)蹋ê拖率龃a示例)將執(zhí)行以下操作:利用命令行參數(shù)傳遞讀取圖像(可以是彩色圖像或灰度圖像),對給定命令行參數(shù)的整數(shù)值進(jìn)行減色。在OpenCV中,主要有三種方式遍歷圖像的每個像素。為了增加實驗的趣味性,會利用這三種方式掃描圖像,并打印出各自花費的時長。

          可以在這里下載完整的源代碼,或者查看OpenCV的cpp教程示例代碼的核心部分。其基本用法是:


          最后一個參數(shù)是可選項,除非加載的是給定的圖像的灰度格式,否則默認(rèn)使用BGR色彩空間。首先,需要做的第一件事是計算查找表。


          首先,利用C ++的stringstream類將第三個命令行參數(shù)由文本格式轉(zhuǎn)換為整數(shù)格式。然后,利用一個看似簡單的公式計算查找表。此時,沒有涉及到OpenCV的具體內(nèi)容。

          接下來的問題是如何測量時間?OpenCV提供了cv::getTickCount()和cv::getTickFrequency() 這兩個簡單的函數(shù)來實現(xiàn)時間的測量。第一個函數(shù)cv::getTickCount()返回返回某個事件(如啟動系統(tǒng))之后系統(tǒng)CPU 的嘀嗒(Tick)數(shù)量。第二個函數(shù)cv::getTickFrequency() 返回CPU每秒鐘發(fā)出多少次嘀嗒聲。有了這兩個函數(shù)之后,便很容易測量出兩個操作之間的時間間隔:

          https://docs.opencv.org/4.5.2/db/de0/group__core__utils.html



          如何在內(nèi)存中存儲圖像矩陣?


          在上一節(jié)Mat-基本圖像容器教程中,講到像素矩陣的大小取決于所使用的色彩系統(tǒng)。更準(zhǔn)確地說,取決于所使用的色彩通道數(shù)。灰度圖像的情況是這樣的:



          多通道圖像的列包含許多子列,子列的數(shù)目即通道的數(shù)量。例如:BGR色彩系統(tǒng)圖像的情況是這樣的:

          注意,在這里通道的順序是相反的:在這里是BGR ,而不是RGB。因為在大多數(shù)情況下,內(nèi)存足夠大,可以一行接一行順序存儲,形成一個單一的長行,有助于加快掃描的速度??梢允褂?cv::Mat::isContinuous()函數(shù)查詢矩陣是否以這種方式存儲。請繼續(xù)閱讀下一節(jié)中的示例。

          cv::Mat::isContinuous()

          https://docs.opencv.org/4.5.2/d3/d63/classcv_1_1Mat.html


          最為有效的方法


          通過經(jīng)典C風(fēng)格操作符(指針)的方式來獲取數(shù)據(jù)是性能最好的方法,因此對于賦值我們推薦的最高效的方法是:


          在這里,只需要獲取每一行起始的指針,然后遍歷到最后一行。在某些特殊情況下,像素矩陣以連續(xù)的方式存儲,只需要一次“請求指針”的操作,便能一路到底遍歷所有的像素。對于彩色圖像有三個色彩通道,每一行需要遍歷三次。

          還有另一種方式:Mat 對象的數(shù)據(jù)成員data 會返回指向第一行、第一列的指針。如果這個指針為空,則這一對象中不存在有效的輸入。利用這種簡單的方法,可以檢查圖像是否成功加載。如果像素存儲是連續(xù)的,我們可以用它來遍歷所有的數(shù)據(jù)指針。如果是灰度圖像, 代碼應(yīng)該是這樣的:


          上述兩種方法會得出相同的結(jié)果。然而,這段代碼閱讀起來會困難得多。如果你有更高級的技術(shù),它閱讀起來會變得更加困難。此外,在實踐中,得到的性能結(jié)果卻是相同的(因為大多數(shù)現(xiàn)代編譯器會自動對代碼進(jìn)行優(yōu)化)。

          迭代器(安全的)方法


          在上述所講的方法中,你要確保傳入正確數(shù)量的uchar數(shù)據(jù)類型值,并跳過行與行之間的間隙,對于用戶來說,迭代器方法(iterator method)被視為是一種更安全的方式, 因為它從用戶那里接管了這些任務(wù)。利用迭代器方法,只需要找出圖像矩陣的起始行和結(jié)尾行,從起始行開始迭代,直到到達(dá)結(jié)尾行。使用*運(yùn)算符獲取迭代器指向的值(在迭代器前添加該符號)。


          對于彩色圖像來說,每一列包含三個UCHAR數(shù)據(jù)項,可以將這三個數(shù)據(jù)項視為一個 UCHAR數(shù)據(jù)類型的短向量,在 OpenCV中,稱之為 Vec3b。用簡單的操作符[]訪問第n個子列。需要記住的重點是:OpenCV的迭代器遍歷這些列,并會自動跳到下一行。因此,在彩色圖像的情況下,如果采用一個簡單的UCHAR迭代器,只能訪問到藍(lán)色通道的值。

          利用引用返回值計算即時地址


          不推薦采用最后一種方法掃描圖像。利用這種方法可以訪問或修改圖像中的隨機(jī)像素,基本的用法是:指定需要訪問元素所在的行數(shù)和列數(shù)。在前面所述的掃描方法中,需要指定數(shù)據(jù)類型,在這里同樣如此,在自動查找之前,需要手動指定使用什么數(shù)據(jù)類型。你可以在以下源代碼的灰度圖像的情況下觀察這一點(用到了+ cv::Mat::at() 函數(shù))


          該函數(shù)根據(jù)輸入的數(shù)據(jù)類型和坐標(biāo),計算出查詢項的地址,然后返回這個地址的引用值。當(dāng)get 這個引用值時,會獲得一個常量,當(dāng)set 這個引用值,它是一個非常量。為了安全起見,僅在調(diào)試模式*,可以檢查輸入坐標(biāo)是否有效,是否確實存在。如果不是在調(diào)試模式下,會有標(biāo)準(zhǔn)錯誤輸出流的錯誤提示。相比于正式發(fā)布模式,二者唯一的區(qū)別是:對于圖像的每一個元素,你將獲得一個新的行指針,用于我們使用 C 運(yùn)算符 [] 獲取列元素的內(nèi)容。

          如果需要使用該方法對圖像做多次查找時,輸入數(shù)據(jù)類型和坐標(biāo)的操作會相當(dāng)麻煩和費時。為解決這一問題,OpenCV添加了 cv::Mat_ 數(shù)據(jù)類型,它與Mat類似,但額外需要在定義時通過要查看的數(shù)據(jù)矩陣的內(nèi)容來指定數(shù)據(jù)類型,但好處是你可以使用()操作符快速訪問矩陣值。更好的是,Mat和cv::Mat數(shù)據(jù)類型之間的可以很方便的進(jìn)行轉(zhuǎn)換。在上述示例中,可以看到這個函數(shù)在彩色圖像中的應(yīng)用。然而,需要注意的是:cv::Mat::at函數(shù)中已經(jīng)包含了相同的操作(具有相同的運(yùn)行速度)。它只是一個偷懶的編程技巧。

          cv::Mat_ 

          https://docs.opencv.org/4.5.2/df/dfc/classcv_1_1Mat__.html


          cv::Mat::at

          https://docs.opencv.org/4.5.2/d3/d63/classcv_1_1Mat.html


          核心功能


          這是在圖像中修改查找表的一個額外獎勵的方法。在圖像處理中, 用戶常常會希望將給定的圖像值修改為其他值。OpenCV提供一個函數(shù),利用這個函數(shù),無需寫入圖像的掃描邏輯,便可修改圖像的像素值。在這里,用到核心模塊的cv::LUT() 函數(shù)。首先,創(chuàng)建一個Mat類型的查找表:

          cv::LUT() 

          https://docs.opencv.org/4.5.2/d2/de8/group__core__array.html



          然后調(diào)用函數(shù),(I是輸入圖像, J是輸出):


          性能差異對比


          編譯并運(yùn)行程序以獲得最佳結(jié)果。為使差別更加明晰,我用了一個相當(dāng)大(2560 X 1600)的彩色圖像。此處介紹的性能適用于彩色圖像. 為了得到更準(zhǔn)確的結(jié)果,我對上百次函數(shù)調(diào)用的結(jié)果做了平均。


          可以得出以下結(jié)論:盡可能使用(而不是徹底改造已有函數(shù))OpenCV已有的函數(shù)。LUT函數(shù)是最快的方法,因為OpenCV庫可以通過英特爾線程構(gòu)建模塊啟用多線程。然而,如果需要編寫一個簡單的圖像掃描方法可選擇指針方法,迭代器是一個更加安全的選擇,但是速度相對來說要慢一些。在調(diào)試模式下,使用引用返回值訪問方法掃描全圖的代價最高;在正式發(fā)布模式下,可能會優(yōu)于迭代方法,但它以犧牲迭代器的安全特性為代價。

          最后,可以觀看YouTube頻道上發(fā)布的程序運(yùn)行視頻。

          https://www.youtube.com/watch?v=fB3AN5fjgwc


          編輯:王菁
          校對:林亦霖

          下一小節(jié):1.3 矩陣的掩膜操作

          往期回顧:
          獨家|OpenCV 1.1 Mat - 基本圖像容器(附鏈接)




          譯者簡介





          陳之炎,北京交通大學(xué)通信與控制工程專業(yè)畢業(yè),獲得工學(xué)碩士學(xué)位,歷任長城計算機(jī)軟件與系統(tǒng)公司工程師,大唐微電子公司工程師,現(xiàn)任北京吾譯超群科技有限公司技術(shù)支持。目前從事智能化翻譯教學(xué)系統(tǒng)的運(yùn)營和維護(hù),在人工智能深度學(xué)習(xí)和自然語言處理(NLP)方面積累有一定的經(jīng)驗。業(yè)余時間喜愛翻譯創(chuàng)作,翻譯作品主要有:IEC-ISO 7816、伊拉克石油工程項目、新財稅主義宣言等等,其中中譯英作品“新財稅主義宣言”在GLOBAL TIMES正式發(fā)表。能夠利用業(yè)余時間加入到THU 數(shù)據(jù)派平臺的翻譯志愿者小組,希望能和大家一起交流分享,共同進(jìn)步

          翻譯組招募信息

          工作內(nèi)容:需要一顆細(xì)致的心,將選取好的外文文章翻譯成流暢的中文。如果你是數(shù)據(jù)科學(xué)/統(tǒng)計學(xué)/計算機(jī)類的留學(xué)生,或在海外從事相關(guān)工作,或?qū)ψ约和庹Z水平有信心的朋友歡迎加入翻譯小組。

          你能得到:定期的翻譯培訓(xùn)提高志愿者的翻譯水平,提高對于數(shù)據(jù)科學(xué)前沿的認(rèn)知,海外的朋友可以和國內(nèi)技術(shù)應(yīng)用發(fā)展保持聯(lián)系,THU數(shù)據(jù)派產(chǎn)學(xué)研的背景為志愿者帶來好的發(fā)展機(jī)遇。

          其他福利:來自于名企的數(shù)據(jù)科學(xué)工作者,北大清華以及海外等名校學(xué)生他們都將成為你在翻譯小組的伙伴。


          點擊文末“閱讀原文”加入數(shù)據(jù)派團(tuán)隊~



          轉(zhuǎn)載須知

          如需轉(zhuǎn)載,請在開篇顯著位置注明作者和出處(轉(zhuǎn)自:數(shù)據(jù)派ID:DatapiTHU),并在文章結(jié)尾放置數(shù)據(jù)派醒目二維碼。有原創(chuàng)標(biāo)識文章,請發(fā)送【文章名稱-待授權(quán)公眾號名稱及ID】至聯(lián)系郵箱,申請白名單授權(quán)并按要求編輯。

          發(fā)布后請將鏈接反饋至聯(lián)系郵箱(見下方)。未經(jīng)許可的轉(zhuǎn)載以及改編者,我們將依法追究其法律責(zé)任。



          點擊“閱讀原文”擁抱組織



          瀏覽 56
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产theporn | 国产夫妻自拍性爱视频 | 天天松天天干天天操天天添 | 操逼视频免费 | 一区不卡 |