CUDA 并行算法Scan卵迂、Reduce 圖像直方圖均衡

1、并行算法介紹

Reduce:

對于一般可以加法運算绒净,如進(jìn)行8個數(shù)相加:


串行計算

由于對于符合交換律见咒,其運算順序可以改變,可以使用并行計算疯溺,如下:


并行計算

對比串行運算论颅,與并行運算的速度:

運算量 8 ... N
并行Step 7 ... N-1
串行Step 3 ... log2(N)

對于并行計算的實現(xiàn),可參照udacity的課程GitHub:reduce.cu

Scan

Scan 可稱為prefix sum囱嫩,即求前N項(或N-1項)的和恃疯,如下:

prefix sum

串行計算流程如上求和無太大差異,而并行計算起來相當(dāng)講技巧墨闲,以N=8舉例:
黑\紅實線:加法 黑虛線:賦值

詳細(xì)可閱讀:Parallel prefix sum (scan) with CUDA

2今妄、圖像的直方圖均衡

假設(shè)存在8個灰度級的圖像如下圖,那么它實際可見的范圍為1~4

1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4

頻數(shù)圖如下:


image.png
histogram_equalize.png

即原來的灰度級為1映射后為0鸳碧,2映射后為2盾鳞,3映射后為3,4映射后為5
均衡后新灰度頻數(shù)表如下:

灰度級 0 1 2 3 4 5 6 7
頻數(shù) 4 0 4 4 0 4 0 0
image.png

映射結(jié)果:

0 2 3 5
0 2 3 5
0 2 3 5
0 2 3 5

總的來說沒有整個過程沒有改變像素點灰度值點之間大小瞻离、數(shù)量關(guān)系腾仅,或者說將可視區(qū)間拉伸,讓色彩對比度更加明顯套利。

3推励、并行圖像直方圖均衡化

1)統(tǒng)計每個灰度級像素的數(shù)目

__global__ void  histogram_init(char *src,unsigned int *out)
//針對512*512大小灰度圖 開啟512*512線程鹤耍,計算256個灰度級相應(yīng)頻數(shù)

2)應(yīng)用Parallel Scan(prefix sum) 計算出映射關(guān)系

__global__ void scan_downsweep(unsigned int *in,unsigned int *out,int n)
//輸入256點頻數(shù)表,輸出均衡化后256對應(yīng)得映射值

3)將原圖按照映射關(guān)系映射到結(jié)果圖

__global__ void equal_remap(char *img,char *out,unsigned int *idetity)
//根據(jù)映射表验辞,重新映射圖像

程序效果圖如下:


histogram_result

源代碼:

#include "cuda.h"
#include "cuda_runtime.h"
#include "cuda_runtime_api.h"
#include "device_functions.h"

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include "stdio.h"
#include <vector>
using namespace std;
using namespace cv;
#define IMAGE_DIR "/home/dzqiu/Documents/image/chaozhou.JPG"

__global__ void  histogram_init(char *src,unsigned int *out)
{
    int x = threadIdx.x + blockDim.x * blockIdx.x;
    int y = threadIdx.y + blockDim.y * blockDim.y;
    int offset = x + y * gridDim.x * blockDim.x;

    unsigned char value = src[offset];
    //原子操作稿黄,否則會出錯。
    atomicAdd(&out[value],1);
}

//refer: Parallel Prefix Sum (Scan) with CUDA, Mark Harris, April 2007
//link : http: //developer.download.nvidia.com/compute/cuda/2_2/sdk/website/projects/scan/doc/scan.pdf
__global__ void scan_downsweep(unsigned int *in,unsigned int *out,int n)
{
    int Idx = threadIdx.x ;
     extern __shared__ float sdata[];
    sdata[Idx] = in[Idx];
    __syncthreads();

    unsigned int offset=1;

    for(unsigned int i=n>>1;i>0;i>>=1)  //build sum iin place up the tree
    {
        __syncthreads();
        if(Idx<i)
        {
            int ai = offset*(2*Idx+1)-1;
            int bi = offset*(2*Idx+2)-1;
            sdata[bi] += sdata[ai];
        }
        offset *= 2 ;
    }

    if(Idx==0) sdata[n-1]=0;            //travers down tree &build scan
    for(unsigned int i=1;i<n;i<<=1)
    {
        offset >>= 1;
        __syncthreads();
        if(Idx<i)
        {
            int ai = offset*(2*Idx+1)-1;
            int bi = offset*(2*Idx+2)-1;

            int tmp    =sdata[ai];
            sdata[ai]  =   sdata[bi];
            sdata[bi] +=   tmp;
        }
    }
    __syncthreads();
    //out[Idx]=sdata[Idx];
    out[Idx]=((float)sdata[Idx]/512/512*256)-1;
}
__global__ void equal_remap(char *img,char *out,unsigned int *idetity)
{
    int x = threadIdx.x+blockIdx.x*blockDim.x;
    int y = threadIdx.y+blockIdx.y*blockDim.y;
    int offset = x+y*blockDim.x*gridDim.x;

    unsigned char value = img[offset];

    out[offset] = (unsigned char) idetity[value];


}

#define DIM             512
#define GRAY_IDENTITY   256
int main(int argc,char** argv)
{

    Mat img_src = imread(IMAGE_DIR);
    Mat img_gray;
    cvtColor(img_src,img_gray,CV_RGB2GRAY);
    resize(img_gray,img_gray,Size(DIM,DIM));

    unsigned int *dev_histogram;
    cudaMalloc((void**)&dev_histogram,GRAY_IDENTITY*sizeof(int));
    cudaMemset(dev_histogram,0,GRAY_IDENTITY*sizeof(int));

    /*build the histogram of the image*/
    char *dev_gray;
    cudaMalloc((void**)&dev_gray,DIM*DIM);
    cudaMemcpy(dev_gray,img_gray.data,DIM*DIM,cudaMemcpyHostToDevice);
    dim3 blocks(DIM/16,DIM/16);dim3 threads(16,16);
    histogram_init<<<blocks,threads>>>(dev_gray,dev_histogram);
    int host_histogram[GRAY_IDENTITY]={0};
    cudaMemcpy(host_histogram,dev_histogram,GRAY_IDENTITY*sizeof(int),cudaMemcpyDeviceToHost);

    /*equalize the histogram*/
    unsigned int *dev_histogram_equal;
    cudaMalloc((void**)&dev_histogram_equal,GRAY_IDENTITY*sizeof(int));
    blocks=dim3(1,1);threads=dim3(GRAY_IDENTITY,1);
    scan_downsweep<<<blocks,threads,sizeof(int)*GRAY_IDENTITY>>>(dev_histogram,dev_histogram_equal,GRAY_IDENTITY);
    int host_histogram_equal[GRAY_IDENTITY]={0};
    cudaMemcpy(host_histogram_equal,dev_histogram_equal,GRAY_IDENTITY*sizeof(int),cudaMemcpyDeviceToHost);

    for(int i=0;i<GRAY_IDENTITY/4;i++)
    {
       //if(host_histogram[i]!=0)
         printf("bin[%3d]:%6d -> %6d| bin[%3d]:%6d -> %6d| bin[%3d]:%6d -> %6d| bin[%3d]:%6d -> %6d\n",
                4*i,host_histogram[4*i],host_histogram_equal[4*i],
                4*i+1,host_histogram[4*i+1],host_histogram_equal[4*i+1],
                4*i+2,host_histogram[4*i+2],host_histogram_equal[4*i+2],
                4*i+3,host_histogram[4*i+3],host_histogram_equal[4*i+3]);
    }

    /*remap the image use the equalized histogram*/
    char *dev_equalImg;
    cudaMalloc((void**)&dev_equalImg,DIM*DIM);
    blocks=dim3(DIM/16,DIM/16);threads=dim3(16,16);
    equal_remap<<<blocks,threads>>>(dev_gray,dev_equalImg,dev_histogram_equal);
    Mat equalImg(DIM,DIM,CV_8UC1,Scalar(255));
    cudaMemcpy(equalImg.data,dev_equalImg,DIM*DIM,cudaMemcpyDeviceToHost);




    cudaFree(dev_gray);
    cudaFree(dev_histogram);
    cudaFree(dev_histogram_equal);
    imshow("gray_img",img_gray);
    imshow("histogram equalization use GPU",equalImg);

    waitKey(0);
    return 0;
}

源碼下載:GitHub
參考:Parallel Prefix Sum (Scan) with CUDA, Mark Harris, April 2007

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末跌造,一起剝皮案震驚了整個濱河市杆怕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌壳贪,老刑警劉巖陵珍,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異撑碴,居然都是意外死亡撑教,警方通過查閱死者的電腦和手機朝墩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進(jìn)店門醉拓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人收苏,你說我怎么就攤上這事亿卤。” “怎么了鹿霸?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵排吴,是天一觀的道長。 經(jīng)常有香客問我懦鼠,道長钻哩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任肛冶,我火速辦了婚禮街氢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘睦袖。我一直安慰自己珊肃,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布馅笙。 她就那樣靜靜地躺著伦乔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪董习。 梳的紋絲不亂的頭發(fā)上烈和,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天,我揣著相機與錄音皿淋,去河邊找鬼招刹。 笑死虱颗,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蔗喂。 我是一名探鬼主播忘渔,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼缰儿!你這毒婦竟也來了畦粮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤乖阵,失蹤者是張志新(化名)和其女友劉穎宣赔,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瞪浸,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡儒将,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了对蒲。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钩蚊。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蹈矮,靈堂內(nèi)的尸體忽然破棺而出砰逻,到底是詐尸還是另有隱情,我是刑警寧澤泛鸟,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布蝠咆,位于F島的核電站,受9級特大地震影響北滥,放射性物質(zhì)發(fā)生泄漏刚操。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一再芋、第九天 我趴在偏房一處隱蔽的房頂上張望菊霜。 院中可真熱鬧,春花似錦祝闻、人聲如沸占卧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽华蜒。三九已至,卻和暖如春豁遭,著一層夾襖步出監(jiān)牢的瞬間叭喜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工蓖谢, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留捂蕴,地道東北人譬涡。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像啥辨,于是被迫代替她去往敵國和親涡匀。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 直方圖變換 灰度變換 點運算 幾何變換 直方圖變換 1.灰度直方圖 灰度直方圖:數(shù)字圖像中每一灰度級像素出現(xiàn)的頻次...
    hyfine閱讀 4,782評論 0 0
  • 先來看看直方圖均衡化的效果圖。 直觀感受级乍,均衡化后的圖像明暗對比更明顯舌劳。亮的地方更亮,暗的地方更暗玫荣,拉開了差距甚淡。1...
    ck2016閱讀 10,116評論 0 4
  • 圖像直方圖(英語:Image Histogram)是用以表示數(shù)字圖像中亮度分布的直方圖,標(biāo)繪了圖像中每個亮度值的像...
    fengzhizi715閱讀 10,008評論 1 6
  • 他和她的未盡之言 可以是一種特殊的香氣 流下你的眼淚 雖然心是干涸 遙遠(yuǎn)的思念 在詩人筆下低沉婉轉(zhuǎn) 似乎都流轉(zhuǎn)歸來...
    秋空積雨閱讀 292評論 0 0
  • 【三件事】 1捅厂,幫嬸嬸修電腦 2贯卦,keep 3/100 3,懂你課程1/100 【小確幸】 思路變清晰 【感悟】 ...
    Sabrina和向日葵閱讀 266評論 0 0