1. 程式人生 > >-01-RGB彩色影象轉換為灰度影象【ARM NEON加速】

-01-RGB彩色影象轉換為灰度影象【ARM NEON加速】

1. NEON簡介

NEON官方的簡介網址:NEON
NEON的主要特點就是single instruction, multiple data(SIMD),擁有專用的ALU和暫存器(d0-d32,q0-q16),基於這種結構很容易實現資料的平行計算,尤其是數學中的向量計算、音訊中雙聲道資料處理、影象中RGB或RGBA彩色影象處理。
SIMD的執行方式如下圖:
SIMD

2. NEON加速例項,RGB2GRAY

從攝像頭或圖片中讀取到的影象通常為彩色的,在進行處理之前需要將其轉換為灰度影象。也就是Matlab,OpenCV中常用到的rgb2gray函式。
在計算機顯示中彩色影象一般由RGB三色組成,若要將其轉換為灰度影象,各通道顏色因為人眼的原因,權值有所不同,公式為:
Gray = R*0.299 + G*0.587 + B*0.114
而在計算機中為了加快運算速度,可以將上面的公式轉化為整數運算,公式為:
Gray = (R * 77 + G * 151 + B * 28 ) / 256
用C語言來實現灰度轉換的程式碼如下:

void reference_convert (uint8_t * __restrict dest, uint8_t * __restrict src, int n)
{
  int i;
  for (i=0; i<n; i++)
  {
    int r = *src++; // load red
    int g = *src++; // load green
    int b = *src++; // load blue 

    // build weighted average:
    int y = (r*77)+(g*151)+(b*28);

    // undo the scale by 256
and write to memory: *dest++ = (y>>8); } }

接下來就參照參考文件1裡面的設計對這個函式進NEON程式碼的編寫。大家可以自己去看一遍。
參考文件首先參照C程式碼的方式,使用編譯器行內函數(compiler intrinsics)在C語言中呼叫了NEON指令,實現了運算加速。接著又參考了編譯器生成的彙編程式碼,直接編寫了NEON程式碼。最終,彩色轉灰度運算實現了NEON加速,運算週期是直接使用C語言生成的7.5倍。下面是三種方式分別實現後,每個畫素需要處理的指令週期。

  C-version:       15.1 cycles per pixel.
NEON-version: 9.9 cycles per pixel. Assembler: 2.0 cycles per pixel.

該例子中NEON的加速是還沒有針對A8處理器中的dual-issue特性進行特別的優化、沒有使用資料預載入指令的效果,可見NEON的並行運算加速功能還是很強的。例子最後的彙編程式碼如下:

convert_asm_neon:
      # r0: Ptr to destination data
      # r1: Ptr to source data
      # r2: Iteration count:
      push        {r4-r5,lr}
      lsr         r2, r2, #3
      # build the three constants:
      mov         r3, #77
      mov         r4, #151
      mov         r5, #28
      vdup.8      d3, r3
      vdup.8      d4, r4
      vdup.8      d5, r5
  .loop:
      # load 8 pixels:
      vld3.8      {d0-d2}, [r1]!
      # do the weight average:
      vmull.u8    q3, d0, d3
      vmlal.u8    q3, d1, d4
      vmlal.u8    q3, d2, d5
      # shift and store:
      vshrn.u16   d6, q3, #8
      vst1.8      {d6}, [r0]!
      subs        r2, r2, #1
      bne         .loop
      pop         { r4-r5, pc }

與C語言中一次處理一個畫素的方式不同,彙編程式碼中是一次進行8個畫素點的灰度計算的。彙編程式碼中的迴圈,一次性從記憶體中讀取8個畫素點的RGB值共24個位元組(vld3.8),進行了1次乘法運算(vmull)、2次乘加運算(vmlal)以及1次移位運算(vshrn)得到8個畫素點的灰度值,並最終儲存到連續的8位元組記憶體當中(vst1.8)。
這中間的乘法、乘加、移位運算都是以向量方式並行運算的,一次能處理8個畫素的資料。這也就是NEON能夠實現程式加速的關鍵所在。

在前面也提到例子中的彙編程式碼還是有可以優化的空間的,主要包含兩個方面:dual-issue和預載入。

  • ARM彙編指南文件中包含了所有的NEON彙編指令格式及用法。

  • dual-issue在neon_tutorial 這個ppt裡面有說明,優化的基本原理就是連續兩條NEON彙編指令中,第一條指令目的運算元得到結果的指令週期與第二條指令的源運算元的準備週期相近或相同,就能夠提高指令、資料處理的並行性。每個NEON彙編指令具體的指令週期需要檢視文件(針對A9晶片) DDI0409G_cortex_a9_neon_mpe_r3p0_trm](http://101.96.8.165/infocenter.arm.com/help/topic/com.arm.doc.ddi0409g/DDI0409G_cortex_a9_neon_mpe_r3p0_trm.pdf)。
    如PPT中的標記出了VEXT和VMLA的指令延時,VEXT得目的運算元結果延時為2,VMLA的源運算元準備延時為2,所以這兩個指令可以配對使用形成dual-issue。
    這裡寫圖片描述
    當然,你的彙編程式碼中需要同時包含這兩個指令才能形成配對,而且在指令調整順序時不能夠影響計算結果才行。

  • pld預載入。前一篇轉載的文件也正是由於用到了PLD指令,在運算迴圈中提前載入了下一次迴圈中需要用到的資料到快取,才實現了很大程度上的資料處理加速。因此,在彙編迴圈程式碼中的合適位置增加PLD指令,能夠大大提高快取命中率,提高程式程式碼的處理速度的。

3. RGB2GRAY的NEON加速優化

雖然前面說到了dual-issue的優化可能性,但是在RGB2GRAY程式碼中,迴圈中的處理的指令僅僅有乘、乘加、移位幾條指令,並不能夠達成dual-issue優化的目的,所以在此不進行優化。
而PLD指令的預載入可以針對r1暫存器進行提前載入,提高快取命中率。
彙編指令格式為:

pld [r1, #24]
pld [r1, #48]

至於具體的預載入偏移,我還沒有詳細測試。但是可以肯定的一點是加入PLD指令後,每畫素的灰度化指令週期一定會更低。

相關推薦

-01-RGB彩色影象轉換影象ARM NEON加速

1. NEON簡介 NEON官方的簡介網址:NEON NEON的主要特點就是single instruction, multiple data(SIMD),擁有專用的ALU和暫存器(d0-d32,q0-q16),基於這種結構很容易實現資料的平行計算,尤其是數學中的向量計算、音訊中雙聲道資料處理、影象中RG

彩色影象轉換影象

方法一:     對於彩色轉灰度,有一個很著名的心理學公式:                           Gray = R*0.299 + G*0.587 + B*0.114      方法二:      而實際應用時,希望避免低速的浮點運算,所以需要整數演算法

BMP--24位真彩色轉換影象

以下文字內容來自http://zhidao.baidu.com/question/152910968.html中的部分內容 把RGB值轉換為灰度值的公式: Gray   :=   Trunc(0.3   *   Red   +   0.59   *   Green  

彩色影象批量轉換影象

       最近在做haar分類器的訓練,要用到大量的正負樣本,在網上找了一些,有一份樣本集除了它是彩色影象外還算滿意,為了後期訓練時間能夠縮短一點,決定把它們都轉換成灰度影象!       說幹就幹,一幅影象的轉換很簡單了,但是批量轉換就稍微複雜了一丟丟,在網上找了下沒

利用OpenCV的imread將RGB影象轉化影象!

通常,我們是利用cvtColor將影象轉化為灰度圖,但實際上在讀取影象的時候便可以將影象轉化為灰度圖, 很簡單的操作,只需要將imread的第二個引數置為0即可 如下面的程式碼: cv::Mat srcImage = cv::imread("lakeWater.jpg"

影象RGB轉換值的四個方法

前言 影象從RGB值轉灰度值非常重要,下面介紹四個方法. 1.opencv中的cv2.imread()方法 import cv2 img0 = cv2.imread('image0.jpg', 0) cv2.imshow('image',img0)

如何使用 python3 將RGB 圖片轉換

首先,介紹第一種方法, 使用  PIL  庫,   PIL庫是一種python語言常用的一個圖形處理庫。 關於   PIL  庫的安裝本文就不介紹了。   from PIL import Image I = Image

RGB轉換影象

RGB轉換成灰度影象的一個常用公式是: Gray = R*0.299 + G*0.587 + B*0.114 //******************灰度轉換函式************************* //第一個引數image輸入的彩色RGB影象的引用; //第二個引數imageGray是轉換後輸

60701BMP彩色影象轉化及二值影象

1 概述   多媒體技術是一門綜合了多種學科的新技術,其涉及到電腦科學與技術、通訊和網路技術、人工智慧技術、微電子技術、數字訊號處理、圖形處 理技術、聲像技術等諸多學科。許多新技術的不斷出現和體驗,帶給人們工作和生活巨大的改變。其應用已經滲透到社會生活和工作的各個方面。   1.1背景

轉變影象的演算法優化及馬賽克實現程式碼

彩色影象轉為灰度影象:   1.三個顏色通道畫素值加和取均值(B+G+R)/3;   2.三個通道按照公式:r*0.299+g*0.587+b*0.114   計算效率:定點大於浮點,+-  >  */,移位(左移<<為乘,右移>>為除)大於乘除,所以演

二值影象:B&W(黑白影象)、 Gray (影象) 、單色影象//Color(彩色影象)

二值影象(binary image),即影象上的每一個畫素只有兩種可能的取值或灰度等級狀態,人們經常用黑白、B&W、單色影象表示二值影象。 B&W黑白影象: 只有黑色和白色,不存在過渡性的灰色,它一個畫素只需要一個二進位制位就能表示出來,即0表示

Matlab之索引影象轉化圖和真彩圖

本篇只講應用不講原理 在進行數字影象處理時,需要將影象轉換成灰度圖。如truecolor轉化為灰度圖,可用函式rgb2gray即可實現,語法也比較簡單。如下: grayImage=rgb2gray(srcImage); 載入完圖片後可使用imfinfo()函式檢視影象資

BYTE[]陣列轉化影象CBitimage顯示到mfc視窗中(opencv結果在mfc中的顯示)

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED

24位bmp影象轉成影象

private void 灰度轉換ToolStripMenuItem_Click(object sender, EventArgs e) { if (curBitmap != null) {

彩色影象RGB通道分別讀到三個影象

這個剛開始不知道怎麼弄,後來問了下網友,原來一個spit函式搞定! #include <cv.h> #include <highgui.h> //#include <math.h> int main() { IplImage* s

在python中使用opencv將RGB影象轉換HSV及YCrCb影象(附程式碼)

【時間】2018.11.01 【題目】在python中使用opencv將RGB影象轉換為HSV及YCrCb影象(附程式碼) 目錄 概述 一、程式碼實現 二、執行結果 三、關於HSV及YCrCb的一點補充 3.1HSV顏色空間 3.2 YCRCBA顏色空間

二進位制影象影象RGB影象、索引影象

二進位制影象也稱為二值影象,通常用一個二維陣列來描述,1位表示一個畫素,組成影象的畫素值非0即1,沒有中間值,通常0表示黑色,1表示白色。二進位制影象一般用來描述文字或者圖形,優點是佔用空間少,缺點是當表示人物或者風景影象時只能描述輪廓。 灰度影象也稱單色影象,通常也有一個

二值影象影象彩色影象

二值影象 二值影象(Binary Image),按名字來理解只有兩個值,0和1,0代表黑,1代表白,或者說0表示背景,而1表示前景。其儲存也相對簡單,每個畫素只需要1Bit就可以完整儲存資訊。如果把每個畫素看成隨機變數,一共有N個畫素,那麼二值圖有2的N次方種變化,而8位灰度

NEON 指令集並行技術優化彩色影象Android

  參考原文: android平臺的neon優化策略 Neon Intrinsics各函式介紹 目前市面上主流的旗艦android手機搭載的Soc都是64位的CPU,常見的armv7指令集的公版架構如Cortex-A8,Cortex-A9,Cortex-A15,常見的

img2txt - 將影象轉換各種基於文字的彩色檔案

img2txt可以轉化為彩色的圖案,你還可以指定圖案大小。 語法:       img2txt [ -W width ] [ -H height ] [ -x font-width ] [ -y font-height ]