2017-04-13 48 views
1

我試圖優化一個平滑的函數,給定圖像平滑/模糊邊緣,用圖像中的每個像素代替周圍像素的平均值(圖像的維度是矩陣)。優化的代碼如下:c代碼優化的光滑功能

int i, j, ii, jj; 
pixel_sum ps; 

for (j = 0; j < dim; j++){ 
    for (i = 0; i < dim; i++){ 
     initialize_pixel_sum(&ps); 
     for(ii = max(i-1, 0); ii <= min(i+1, dim-1); ii++){ 
      for(jj = max(j-1, 0); jj <= min(j+1, dim-1); jj++){ 
       accumulate_sum(&ps, src[RIDX(ii,jj,dim)]); 
      } 
     } 
     dst[RIDX(i,j,dim)].red = ps.red/ps.num; 
     dst[RIDX(i,j,dim)].green = ps.green/ps.num; 
     dst[RIDX(i,j,dim)].blue = ps.blue/ps.num; 
    } 
} 

我發現了一個優化的版本,這看起來像下面:

int i, j, myJ; 

//cornors 
dst[0].red = (src[0].red+src[1].red+src[dim].red+src[dim+1].red)>>2; 
dst[0].blue = (src[0].blue+src[1].blue+src[dim].blue+src[dim+1].blue)>>2; 
dst[0].green = (src[0].green+src[1].green+src[dim].green+src[dim+1].green)>>2; 

i = dim*2-1; 
dst[dim-1].red = (src[dim-2].red+src[dim-1].red+src[i-1].red+src[i].red)>>2; 
dst[dim-1].blue = (src[dim-2].blue+src[dim-1].blue+src[i-1].blue+src[i].blue)>>2; 
dst[dim-1].green = (src[dim-2].green+src[dim-1].green+src[i-1].green+src[i].green)>>2; 

j = dim*(dim-1); 
i = dim*(dim-2); 
dst[j].red = (src[j].red+src[j + 1].red+src[i].red+src[i + 1].red)>>2; 
dst[j].blue = (src[j].blue+src[j + 1].blue+src[i].blue+src[i + 1].blue)>>2; 
dst[j].green = (src[j].green+src[j + 1].green+src[i].green+src[i + 1].green)>>2; 

j = dim*dim-1; 
i = dim*(dim-1)-1; 
dst[j].red = (src[j - 1].red+src[j].red+src[i - 1].red+src[i].red)>>2; 
dst[j].blue = (src[j - 1].blue+src[j].blue+src[i - 1].blue+src[i].blue)>>2; 
dst[j].green = (src[j - 1].green+src[j].green+src[i - 1].green+src[i].green)>>2; 

//sides 
i = dim - 1; 
for (j = 1; j < i; j++) 
{ 
    dst[j].red = (src[j].red+src[j-1].red+src[j+1].red+src[j+dim].red+src[j+1+dim].red+src[j-1+dim].red)/6; 
    dst[j].green = (src[j].green+src[j-1].green+src[j+1].green+src[j+dim].green+src[j+1+dim].green+src[j-1+dim].green)/6; 
    dst[j].blue = (src[j].blue+src[j-1].blue+src[j+1].blue+src[j+dim].blue+src[j+1+dim].blue+src[j-1+dim].blue)/6; 
} 

i = dim*dim-1; 
for (j = i - dim + 2; j < i; j++) 
{ 
    dst[j].red = (src[j].red+src[j-1].red+src[j+1].red+src[j-dim].red+src[j+1-dim].red+src[j-1-dim].red)/6; 
    dst[j].green = (src[j].green+src[j-1].green+src[j+1].green+src[j-dim].green+src[j+1-dim].green+src[j-1-dim].green)/6; 
    dst[j].blue = (src[j].blue+src[j-1].blue+src[j+1].blue+src[j-dim].blue+src[j+1-dim].blue+src[j-1-dim].blue)/6; 
} 

for (j = dim+dim-1; j < dim*dim-1; j+=dim) 
{ 
    dst[j].red = (src[j].red+src[j-1].red+src[j-dim].red+src[j+dim].red+src[j-dim-1].red+src[j-1+dim].red)/6; 
    dst[j].green = (src[j].green+src[j-1].green+src[j-dim].green+src[j+dim].green+src[j-dim-1].green+src[j-1+dim].green)/6; 
    dst[j].blue = (src[j].blue+src[j-1].blue+src[j-dim].blue+src[j+dim].blue+src[j-dim-1].blue+src[j-1+dim].blue)/6; 
} 

i = i - (dim - 1); 
for (j = dim; j < i; j+=dim) 
{ 
    dst[j].red = (src[j].red+src[j-dim].red+src[j+1].red+src[j+dim].red+src[j+1+dim].red+src[j-dim+1].red)/6; 
    dst[j].green = (src[j].green+src[j-dim].green+src[j+1].green+src[j+dim].green+src[j+1+dim].green+src[j-dim+1].green)/6; 
    dst[j].blue = (src[j].blue+src[j-dim].blue+src[j+1].blue+src[j+dim].blue+src[j+1+dim].blue+src[j-dim+1].blue)/6; 
} 

myJ = dim; 

for (i = 1; i < dim-1; i++) 
{ 
    for (j = 1; j < dim-1; j++) 
    { 
     myJ ++; 
     dst[myJ].red = (src[myJ-1].red+src[myJ].red+src[myJ+1].red+src[myJ-dim-1].red+src[myJ-dim].red+src[myJ-dim+1].red+src[myJ+dim-1].red+src[myJ+dim].red+src[myJ+dim+1].red)/9; 
     dst[myJ].green = (src[myJ-1].green+src[myJ].green+src[myJ+1].green+src[myJ-dim-1].green+src[myJ-dim].green+src[myJ-dim+1].green+src[myJ+dim-1].green+src[myJ+dim].green+src[myJ+dim+1].green)/9; 
     dst[myJ].blue = (src[myJ-1].blue+src[myJ].blue+src[myJ+1].blue+src[myJ-dim-1].blue+src[myJ-dim].blue+src[myJ-dim+1].blue+src[myJ+dim-1].blue+src[myJ+dim].blue+src[myJ+dim+1].blue)/9; 
    } 
    myJ += 2; 
} 

有人能解釋這是如何優化工作?

回答

1

由於您沒有顯示很多東西的定義(accumulate_sumpixel_sum,RIDX等),因此很難確定。看起來代碼的第一個版本按行和列迭代數據,第二個版本首先處理角點,然後處理邊緣,然後處理其餘數據。您正在處理基於其周圍像素的像素。角點和邊緣的相鄰像素較少,因此處理它們更容易一些。打破這些特殊情況可以使其代碼簡化。第二個版本然後是unrolls最裏面的兩個循環,同時處理其餘的數據,這是唯一可能的,因爲你已經消除了所有的特殊情況(邊緣和角落)。

這個改變是否實際上是一個「優化」,是讀者留下的練習。你需要在兩個版本上運行性能測試來確定。即使第二個版本效率更高,第一個版本的可讀性也要高得多。