在Renderscript直方图匹配 [英] Histogram Matching in Renderscript

查看:260
本文介绍了在Renderscript直方图匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了对齐两个灰度图像的亮度值(作为进一步处理的第一步),我写了一个Java方法:

In order to align the intensity values of two grayscale Images (as a first step for further processing) I wrote a Java method that:


  1. 转换两个图像的位图到含有位图的强度两个 INT [] 阵列(我只取红色分量在这里,因为它的灰度,即R = G = b)。

  1. converts the bitmaps of the two images into two int[] arrays containing the bitmap's intensities (I just take the red component here, since it's grayscale, i.e. r=g=b ).

public static int[] bmpToData(Bitmap bmp){
int width = bmp.getWidth();
int height = bmp.getHeight();
int anzpixel = width*height;
int [] pixels = new int[anzpixel];
int [] data = new int[anzpixel];  
bmp.getPixels(pixels, 0, width, 0, 0, width, height);
for (int i = 0 ; i < anzpixel ; i++) {
int p = pixels[i];
int r = (p & 0xff0000) >> 16;
//int g = (p & 0xff00) >> 8;
//int b = p & 0xff;
data[i] = r;
}
return data;
}


  • 对齐位图2的累积强度分布到该位图1

  • aligns the cumulated intensity distributions of Bitmap 2 to that of Bitmap 1

        //aligns the intensity distribution of a grayscale picture moving    (given by int[] //data2) the the intensity distribution of a reference picture fixed (given by // int[] data1)
    public static int[] histMatch(int[] data1, int[] data2){
    
       int anzpixel = data1.length;
       int[] histogram_fixed = new int[256];
       int[] histogram_moving = new int[256];
       int[] cumhist_fixed = new int[256];
       int[] cumhist_moving = new int[256];
       int i=0;
       int j=0;
    
       //read intensities of fixed und moving in histogram
       for (int n = 0; n < anzpixel; n++) {
          histogram_fixed[data1[n]]++;
          histogram_moving[data2[n]]++;
       }
    
       // calc cumulated distributions
       cumhist_fixed[0]=histogram_fixed[0];
       cumhist_moving[0]=histogram_moving[0];
       for ( i=1; i < 256; ++i ) {
          cumhist_fixed[i] = cumhist_fixed[i-1]+histogram_fixed[i];
          cumhist_moving[i] = cumhist_moving[i-1]+histogram_moving [i];
       }
    
       // look-up-table lut[]. For each quantile i of the moving picture search     the 
       // value j of the fixed picture where the quantile is the same as that of moving   
       int[] lut = new int[anzpixel];
       j=0;
       for ( i=0; i < 256; ++i ){
          while(cumhist_fixed[j]< cumhist_moving[i]){
             j++;
          }
    
          // check, whether the distance to the next-lower intensity is even lower, and if so, take this value
          if ((j!=0) && ((cumhist_fixed[j-1]- cumhist_fixed[i]) < (cumhist_fixed[j]- cumhist_fixed[i]))){
             lut[i]= (j-1);
          }
          else {
             lut[i]= (j);
          }
       }
    
       // apply the lut[] to moving picture.
       i=0;
       for (int n = 0; n < anzpixel; n++) {
          data2[n]=(int) lut[data2[n]];
       }
       return data2;
    }
    


  • INT [] 数组转换回位图。

    public static Bitmap dataToBitmap(int[] data, int width, int heigth) {
     int index=0;
     Bitmap bmp = Bitmap.createBitmap(width, heigth, Bitmap.Config.ARGB_8888);
     for (int x = 0; x < width; x++) {
      for (int y = 0; y < heigth; y++) {
         index=y*width+x;
         int c = data[index];
         bmp.setPixel(x,y,Color.rgb(c, c, c));
         }
     }
     return bmp;
    }
    


  • 尽管核心程序2)是直接和快速的,转换的步骤1)和3)是相当低效率的。这将是酷比更多的工作要做整个事情的Renderscript。但是,说实话,我完全这样做,因为丢失的文件,所以丢失,同时有什么Renderscript可以执行许多IM pressing例子中,我没有看到一个方法来从这些可能性中获益(无书,无实况)。任何意见是高度AP preciated!

    While the core procedure 2) is straightforward and fast, the conversion steps 1) and 3) are rather inefficient. It would be more than cool to do the whole thing in Renderscript. But, honestly, I am completely lost in doing so because of missing documentation and, while there are many impressing examples on what Renderscript COULD perform, I don't see a way to benefit from these possibilities (no books, no docu). Any advice is highly appreciated!

    推荐答案

    作为一个起点,使用Android Studio来导入样品...,然后选择基本渲染脚本。这会给你一个工作项目,我们现在将修改

    As a starting point, use Android Studio to "Import Sample..." and select Basic Render Script. This will give you a working project that we will now modify.

    首先,让我们添加更多的分配引用 MainActivity 。我们将使用他们交流的图像数据,直方图和Java和Renderscript之间的LUT。

    First, let's add more Allocation references to MainActivity. We will use them to communicate image data, histograms and the LUT between Java and Renderscript.

    private Allocation mInAllocation;
    private Allocation mInAllocation2;
    private Allocation[] mOutAllocations;
    private Allocation mHistogramAllocation;
    private Allocation mHistogramAllocation2;
    private Allocation mLUTAllocation;
    

    然后在的onCreate()加载另一个图像,您也将需要添加到/ RES /绘图资源/.

    Then in onCreate() load another image, which you will also need to add to /res/drawables/.

        mBitmapIn2 = loadBitmap(R.drawable.cat_480x400);
    

    createScript()创建额外分配:

        mInAllocation2 = Allocation.createFromBitmap(mRS, mBitmapIn2);
        mHistogramAllocation = Allocation.createSized(mRS, Element.U32(mRS), 256);
        mHistogramAllocation2 = Allocation.createSized(mRS, Element.U32(mRS), 256);
        mLUTAllocation = Allocation.createSized(mRS, Element.U32(mRS), 256);
    

    和现在的主要部分(在 RenderScriptTask

    And now the main part (in RenderScriptTask):

                /*
                 * Invoke histogram kernel for both images
                 */
                mScript.bind_histogram(mHistogramAllocation);
                mScript.forEach_compute_histogram(mInAllocation);
    
                mScript.bind_histogram(mHistogramAllocation2);
                mScript.forEach_compute_histogram(mInAllocation2);
    
    
                /*
                 * Variables copied verbatim from your code.
                 */
                int []histogram_fixed = new int[256];
                int []histogram_moving = new int[256];
                int[] cumhist_fixed = new int[256];
                int[] cumhist_moving = new int[256];
                int i=0;
                int j=0;
    
                // copy computed histograms to Java side
                mHistogramAllocation.copyTo(histogram_fixed);
                mHistogramAllocation2.copyTo(histogram_moving);
    
                // your code again...
                // calc cumulated distributions
                cumhist_fixed[0]=histogram_fixed[0];
                cumhist_moving[0]=histogram_moving[0];
    
                for ( i=1; i < 256; ++i ) {
                    cumhist_fixed[i] = cumhist_fixed[i-1]+histogram_fixed[i];
                    cumhist_moving[i] = cumhist_moving[i-1]+histogram_moving [i];
                }
    
                // look-up-table lut[]. For each quantile i of the moving picture search     the
                // value j of the fixed picture where the quantile is the same as that of moving
                int[] lut = new int[256];
                j=0;
                for ( i=0; i < 256; ++i ){
                    while(cumhist_fixed[j]< cumhist_moving[i]){
                        j++;
                    }
    
                    // check, whether the distance to the next-lower intensity is even lower, and if so, take this value
                    if ((j!=0) && ((cumhist_fixed[j-1]- cumhist_fixed[i]) < (cumhist_fixed[j]- cumhist_fixed[i]))){
                        lut[i]= (j-1);
                    }
                    else {
                        lut[i]= (j);
                    }
                }
    
                // copy the LUT to Renderscript side
                mLUTAllocation.copyFrom(lut);
                mScript.bind_LUT(mLUTAllocation);
    
                // Apply LUT to the destination image
                mScript.forEach_apply_histogram(mInAllocation2, mInAllocation2);
    
    
                /*
                 * Copy to bitmap and invalidate image view
                 */
                //mOutAllocations[index].copyTo(mBitmapsOut[index]);
    
                // copy back to Bitmap in preparation for viewing the results
                mInAllocation2.copyTo((mBitmapsOut[index]));
    

    夫妇注:


    • 在您的code我也定LUT分配大小的一部分 - 只需要256个地址,

    • 正如你所看到的,我离开累积直方图和LUT在Java方面的计算。这是相当困难的高效并行由于数据相关性和计算规模小,但考虑到后者,我不认为这是一个问题。

    最后,Renderscript code。唯一的非明显的部分是采用 rsAtomicInc()来增加值直方图箱 - 这是必要的,因为许多潜在的线程试图同时增加同斌

    Finally, the Renderscript code. The only non-obvious part is the use of rsAtomicInc() to increase values in histogram bins - this is necessary due to potentially many threads attempting to increase the same bin concurrently.

    #pragma version(1)
    #pragma rs java_package_name(com.example.android.basicrenderscript)
    #pragma rs_fp_relaxed
    
    int32_t *histogram;
    int32_t *LUT;
    
    void __attribute__((kernel)) compute_histogram(uchar4 in)
    {
        volatile int32_t *addr = &histogram[in.r];
        rsAtomicInc(addr);
    }
    
    uchar4 __attribute__((kernel)) apply_histogram(uchar4 in)
    {
        uchar val = LUT[in.r];
        uchar4 result;
        result.r = result.g = result.b = val;
        result.a = in.a;
    
        return(result);
    }
    

    这篇关于在Renderscript直方图匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆