2010-10-20 20 views
7

beagleboard üzerinde çalışmak üzere tasarlanmış bazı görüntü işleme algoritmaları uygulamak istiyorum. Bu algoritmalar yoğun olarak konvolüsyonlar kullanır. 2D konvolüsyon için iyi bir C uygulaması bulmaya çalışıyorum (muhtemelen Hızlı Fourier Dönüşümü'nü kullanarak). Algoritmanın beagleboard'un DSP'sinde çalışmasını da istiyorum çünkü DSP'nin bu tür işlemler için optimize edildiğini duydum (çoklu-birikimli talimatı ile).DSP için Hızlı 2B evrişim

Sahada hiç arka planım yok, bu yüzden evrimin benimsenmesi için iyi bir fikir olmayacağını düşünüyorum (muhtemelen bunu arkasındaki tüm matematiği anlayan biri kadar iyi yapmayacağım). DSP için iyi bir C konvolüsyon uygulamasının bir yerde var olduğuna inanıyorum ama bunu bulamadım?

Birisi yardımcı olabilir mi?

DÜZENLEME: Çekirdeğin çekirdeği oldukça küçüktür. Boyutları 2X2 veya 3X3'tür. Yani FFT tabanlı bir uygulama aramıyorum sanırım. İnternette tanımını görmek için evrimleşmeyi araştırıyordum, böylece onu ileriye doğru bir şekilde uygulayabiliyorum (gerçekten evrişimin ne olduğunu bilmiyorum). Tüm bulduğum çarpık integraller ile bir şey ve matrisler ile nasıl yapılacağı hakkında hiçbir fikrim yok. Birisi bana 2X2 çekirdek durumu için bir parça kod (veya sözde kod) verebilir mi?

+0

http://en.wikipedia.org/wiki/Convolution#Discrete_convolution –

+0

@Peter : Teşekkürler, ama burada 1D durumundan bahsediyorlar, 2D konvolüsyonu hakkında hiçbir şey yok – snakile

+0

2d konvolüsyonları (görüntü işleme) genellikle ayrılabilir, bu yüzden sırayla 2 1-d konvolüsyon olarak çalıştırılabilir. Bu işlem gereksinimini çok daha küçük hale getirir. Kullanmak istediğiniz çekirdek çeşitlerinden örnekler verebilir misiniz? –

cevap

11

Görüntünün ve çekirdeğin boyutları nedir? Eğer çekirdek büyükse, FFT-temelli konvolüsyon kullanabilirsiniz, aksi halde küçük taneler için sadece doğrudan konvolüsyon kullanın.

DSP bunu yapmanın en iyi yolu olmayabilir - sadece MAC yönergesinin olması daha verimli olacağı anlamına gelmez. Beagle Board'da ARM CPU'nun NEON SIMD var mı? Öyleyse o zaman gitmek için yol olabilir (ve daha eğlenceli). Küçük bir çekirdeğin için

, böyle direkt konvolüsyonunu yapabilirsiniz:

Sen K hatta değerlerini desteklemek için bu değiştirebilir
// in, out are m x n images (integer data) 
// K is the kernel size (KxK) - currently needs to be an odd number, e.g. 3 
// coeffs[K][K] is a 2D array of integer coefficients 
// scale is a scaling factor to normalise the filter gain 

for (i = K/2; i < m - K/2; ++i) // iterate through image 
{ 
    for (j = K/2; j < n - K/2; ++j) 
    { 
    int sum = 0; // sum will be the sum of input data * coeff terms 

    for (ii = - K/2; ii <= K/2; ++ii) // iterate over kernel 
    { 
     for (jj = - K/2; jj <= K/2; ++jj) 
     { 
     int data = in[i + ii][j +jj]; 
     int coeff = coeffs[ii + K/2][jj + K/2]; 

     sum += data * coeff; 
     } 
    } 
    out[i][j] = sum/scale; // scale sum of convolution products and store in output 
    } 
} 

- bu sadece iki üst/alt sınırlarıyla biraz ilgilenir iç döngüler.

+0

@Paul: Düz-yukarı kıvrımlar için TI'nın modulo adresleme modları ve sıfır-yukarı halkalı döngüler vb. –

+0

@Oli: haklı olabilirsiniz - modulo adreslemenin yardımcı olduğundan emin değilim, ancak başka avantajlar da olabilir. –

+0

@MPaul: Dairesel bir arabellekle sıkıştırma yapıyorsanız Modulo adresleme yardımcı olur. Bunu telafi etmek için hiçbir sayım yok, ama eğer TI ev sahibi işlemciyi tasarladığı kanonik şeyde yenemezse, o zaman oldukça anlamsız bir kombinasyon! –

0

Konudan kaynaklandığını biliyorum ancak C ve JavaScript arasındaki benzerlik nedeniyle, bunun hala yararlı olabileceğine inanıyorum. PS .: @Paul R cevabından esinlenildi. JavaScript

İki boyutlar 2B konvolusyon algoritması kullanarak diziler

function newArray(size){ 
    var result = new Array(size); 
    for (var i = 0; i < size; i++) { 
     result[i] = new Array(size); 
    } 

    return result; 
} 

function convolveArrays(filter, image){ 
    var result = newArray(image.length - filter.length + 1); 

    for (var i = 0; i < image.length; i++) { 
     var imageRow = image[i]; 
     for (var j = 0; j <= imageRow.length; j++) { 

      var sum = 0; 
      for (var w = 0; w < filter.length; w++) { 
       if(image.length - i < filter.length) break; 

       var filterRow = filter[w]; 
       for (var z = 0; z < filter.length; z++) { 
        if(imageRow.length - j < filterRow.length) break; 
        sum += image[w + i][z + j] * filter[w][z]; 
       } 
      } 

      if(i < result.length && j < result.length) 
       result[i][j] = sum; 
     } 
    } 

    return result; 
} 
Sen http://ec2-54-232-84-48.sa-east-1.compute.amazonaws.com/two-dimensional-convolution-algorithm-with-arrays-in-javascript/ tam blog yazısı kontrol edebilirsiniz