簡體   English   中英

C中具有2D函數的浮點圖像卷積

[英]convolution of float image with 2D function in C

您好,我必須使用以下內核對32位原始圖像進行2D卷積

h(x,y)= a(b* exp^(-squareroot(x^2+y^2))

我不知道如何執行它,因為我是初學者。 我的圖片大小是1024 * 768。 我應該保持相同大小的內核並進行卷積還是要保留一個小的內核? 他們兩個會有所作為嗎? 如果我保留一個小的內核,如何將其與整個圖像進行卷積?

請幫忙

請檢查生成內核的代碼是否正確

謝謝你們的回答。 請檢查下面的生成內核代碼和卷積代碼。 我不確定我做得對嗎

int krowhalf = krow / 2,kcolhalf = kcol / 2;

// sum is for normalization
float sum = 0.0;

// generate  kernel
for (int x = -krowhalf; x <= krowhalf; x++)
{
    for(int y = -kcolhalf; y <= kcolhalf; y++)
    {
        r = sqrtl(x*x + y*y);
        gKernel[x + krowhalf][y + kcolhalf] = a*(b*exp(-(r));
        sum += gKernel[x + krowhalf][y + kcolhalf];
    }
}

 //normalize the Kernel
for(int i = 0; i < krow; ++i)
    for(int j = 0; j < kcol; ++j)

gKernel[i][j] /= sum;

  float **convolve2D(float** in, float** out, int h, int v, float **kernel, int kCols,     int kRows)

  {
      int kCenterX = kCols / 2;

      int kCenterY = kRows / 2;

       int i,j,m,mm,n,nn,ii,jj;



     for(i=0; i < h; ++i) 
         // rows
      {
       for(j=0; j < v; ++j)   
   // columns
        {

   for(m=0; m < kRows; ++m)     // kernel rows

    {
       mm = kRows - 1 - m;      // row index of flipped kernel

        for(n=0; n < kCols; ++n) // kernel columns
        {
            nn = kCols - 1 - n;  // column index of flipped kernel

             //index of input signal, used for checking boundary
         ii = i + (m - kCenterY);
          jj = j + (n - kCenterX);

            // ignore input samples which are out of bound
            if( ii >= 0 && ii < h && jj >= 0 && jj < v )

                //out[i][j] += in[ii][jj] * (kernel[mm+nn*29]);
                out[i][j] += in[ii][jj] * (kernel[mm][nn]);


            }
       }
   }
}

返回 }

您知道如何進行一維信號卷積嗎? 您的過濾器始終為有限長度。 您無法使用數字計算機進行無限卷積。 二維濾波器也總是有限長度的。 例如,最簡單的2-D濾波器拉普拉斯算子只有3X3大小。 過濾器越長,處理就越復雜。

好吧,要使用一個非常大的內核(這將是理論上的確切結果)將永遠花費,因此通常除非您確實需要一些精確的東西,否則通常采用3x3或5x5。 如果您仍然使用精度有限的常規浮點數,則更多的變化不太可能。

可以通過遍歷每個點的兩個簡單的for循環進行卷積。 對於邊緣,一種簡單的方法是擴展圖像(例如,如果使用3x3,則在每一側添加一個像素)並從舊邊緣開始循環。

發布代碼后進行編輯:

在循環代碼中使用ifs將阻止編譯器使用更快的指令(除非您的編譯器非常聰明)同時計算更多的點。 這行代碼: out[i][j] += in[ii][jj] * (kernel[mm][nn]); 可以由編譯器轉換為SIMD指令,同時計算4個值。 正因為如此,通常將填充零添加到邊緣並且不使內核位於這些點上更為有效。

計算高斯濾波器的方法有很多(這是圖像處理中的基本方法)。 這取決於您對性能的要求以及要支持的內核大小范圍。

OpenCV和Intel IPP確實支持此過濾器,您可以在Web上輕松找到開放源代碼。 您還可以查看Deriche(遞歸實現高斯及其衍生函數)和van Vliet(高斯濾波器的遞歸實現)特殊算法:無論大小如何,它們都可以通過每個像素固定數量的運算來計算濾波器。

您的實現似乎正確。 無論如何,我建議您使用過濾器的可分離性:2D高斯是通過1D水平高斯,然后是1D垂直( e^-(X²+Y²)=e^-X².e^-Y² )獲得的。 這樣,您只需要krow + kcol即可,而不是每個像素進行krow x kcol操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM