日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

图像处理(五)双指数磨皮

發布時間:2025/3/21 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 图像处理(五)双指数磨皮 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

磨皮對于現在的圖像處理軟件,可以說是一項重要的功能,在天天P圖,可牛,ps,美圖秀秀等軟件中隨處可見,有可能即使你非常熟悉圖像處理的算法,然而卻不懂磨皮怎么實現。其實磨皮就是所謂的保邊緣濾波,也就是說在圖像處理領域只要是濾波算法都可以實現磨皮,只是效果好壞的區別,然而現在對于大部分,都要求具有保細節的功能,這邊先給大家介紹一種算法:雙指數保邊緣濾波,對應的 外圍文獻為:《Bi-Exponential Edge-Preserving Smoother》

下面是這篇文獻最重要的部分,算法整個過程分為三個步驟:

(1)水平方向遞歸:包括對原始圖像的水平方向進行向前遞歸(公式1)、對原始圖片的水平方向進行向后遞歸(公式3),然后把向前遞歸結果、向后遞歸結果、原圖像數據做一個加權組合(公式5),得到新的像素值。

(2)垂直方向遞歸:同樣的對原始圖像數據進行與水平方向的遞歸方式類似的方法,計算得到新的像素值

(3)把垂直遞歸與水平遞歸的結果相加,然后除以2,得到最后的結果

這個算法具有高度并行的效果,因此啟用多線程毫無壓力,而且算法是圖像中常用的遞歸加速,因此速度挺快的,如果還覺得速度不夠快,可以采用查詢表的方式


接著貼一下部分重要函數的代碼,供參考,下面代碼中我用了查詢表的方式進行加速,速度可以比之前提高一倍,效果和原算法肉眼看不出來有什么區別,差別非常小,因此建議用查詢表進行加速,還有其它的一些小細節我也沒有根據原文進行寫代碼。

[cpp]?view plaincopy
  • void?CBeeps::Run(BYTE*?pImage,?int?nWidth,?int?nHeight,?int?nStride)??
  • {??
  • ????if?(pImage?==?NULL)??
  • ????{??
  • ????????return;??
  • ????}??
  • ????m_pImage=pImage;??
  • ????m_nWidth=nWidth;??
  • ????m_nHeight=nHeight;??
  • ????m_nStride=nStride;??
  • ??
  • ????ApplyBiExponentialEdgePreservingSmoother(20,0.02);??
  • }??
  • void?CBeeps::ApplyBiExponentialEdgePreservingSmoother(double?photometricStandardDeviation,?double?spatialDecay)??
  • {??
  • ????m_exp_table=new?double[256];??
  • ????m_g_table=new?double[256];??
  • ????double?c=-0.5/(photometricStandardDeviation?*?photometricStandardDeviation);??
  • ????double?mu=spatialDecay/(2-spatialDecay);??
  • ????for?(int?i=0;i<=255;i++)??
  • ????{??
  • ????????float?a=exp(c*i*i);??
  • ????????m_exp_table[i]=(1-spatialDecay)*?exp(c*i*i);??
  • ????????m_g_table[i]=mu*i;??
  • ????}??
  • ????BYTE*?p0?=m_pImage;??
  • ????const?int?nChannel?=?4;??
  • ????int?m_length?=m_nWidth*m_nHeight;??
  • ????float?maxerror=0;??
  • ????float?sum=0;??
  • ????//?對每個channel進行處理??
  • ????#pragma?omp?parallel?for??
  • ????for?(int?idxChannel=0;idxChannel?<nChannel;?idxChannel++)??
  • ????{??
  • ????????double?*data1?=?new?double[m_length];??
  • ????????double*?data2?=?new?double[m_length];??
  • ????????//double*?data3?=?new?double[m_length];??
  • ????????//double*?data4?=?new?double[m_length];??
  • ????????BYTE?*p1=p0+idxChannel;??
  • ????????for?(int?i?=?0;?i?<?m_length;++i)??
  • ????????{??
  • ????????????data1[i]?=?p1[i?*?nChannel];??
  • ????????}??
  • ????????memcpy(data2,data1,?sizeof(double)?*?m_length);??
  • ????????//memcpy(data3,data1,?sizeof(double)?*?m_length);??
  • ????????//memcpy(data4,data1,?sizeof(double)?*?m_length);??
  • ??
  • ????????//CBEEPSHorizontalVertical?hv(data3,?m_nWidth,?m_nHeight,??photometricStandardDeviation,?spatialDecay);??
  • ????????//hv.run();??
  • ????????//CBEEPSVerticalHorizontal?vh(data4,?m_nWidth,?m_nHeight,?photometricStandardDeviation,?spatialDecay);??
  • ????????//vh.run();??
  • ????????runHorizontalVertical(data1,?m_nWidth,?m_nHeight,spatialDecay,m_exp_table,m_g_table);??
  • ????????runVerticalHorizontal(data2,?m_nWidth,?m_nHeight,spatialDecay,m_exp_table,m_g_table);??
  • ????????sum=0;??
  • ????????for?(int?i?=0;i<m_length;++i)??
  • ????????{??
  • ????????????//double?val?=?(data3[i]?+?data4[i])?*?0.5;??
  • ????????????double?val=(data1[i]?+?data2[i])?*?0.5;??
  • ????????????//double?error0=abs((int)val2-(int)val);??
  • ????????????//sum=sum+error0;??
  • ????????????//if?(error0>maxerror)??
  • ????????????//{??
  • ????????????????//maxerror=error0;??
  • ????????????//}??
  • ????????????if(255.0<val)val=255.0;??
  • ????????????p1[i?*?nChannel]=(BYTE)val;??
  • ?????????}??
  • ????????//sum=sum/m_length;??
  • ????????delete?data1;??
  • ????????delete?data2;??
  • ????}//for??
  • ??????
  • ????delete?m_exp_table;m_exp_table=NULL;??
  • ????delete?m_g_table;m_g_table=NULL;??
  • }??
  • //垂直方向遞歸??
  • void?CBeeps::runVerticalHorizontal(double?*data,int?width,int?height,double?spatialDecay,double?*exp_table,double?*g_table)??
  • {??
  • ????int?length0=height*width;??
  • ????double*?g=?new?double[length0];??
  • ????int?m?=?0;??
  • ????for?(int?k2?=?0;k2<height;++k2)??
  • ????{??
  • ????????int?n?=?k2;??
  • ????????for?(int?k1?=?0;k1<width;++k1)??
  • ????????{??
  • ????????????g[n]=data[m++];??
  • ????????????n?+=?height;??
  • ????????}??
  • ????}??
  • ????double*p?=?new?double[length0];??
  • ????double*r?=?new?double[length0];??
  • ????memcpy(p,?g,?sizeof(double)?*?length0);??
  • ????memcpy(r,?g,?sizeof(double)?*?length0);??
  • ????for?(int?k1?=?0;k1<width;?++k1)??
  • ????{??
  • ????????int?startIndex=k1?*?height;??
  • ????????double?mu?=?0.0;??
  • ????????for?(int?k=startIndex+1,K?=startIndex+height;k<K;++k)??
  • ????????{??
  • ????????????int?div0=fabs(p[k]-p[k-1]);??
  • ????????????mu?=exp_table[div0];??
  • ????????????p[k]?=?p[k?-?1]?*?mu?+?p[k]?*?(1.0?-?mu);//文獻中的公式1,這里做了一下修改,效果影響不大??
  • ????????}??
  • ????????for?(int?k?=startIndex+height-2;startIndex?<=?k;--k)??
  • ????????{??
  • ????????????int?div0=fabs(r[k]-r[k+1]);??
  • ????????????mu?=exp_table[div0];??
  • ????????????r[k]?=?r[k+1]?*?mu?+?r[k]?*?(1.0-mu)?;//文獻公式3??
  • ????????}??
  • ????}??
  • ????double?rho0=1.0/(2-spatialDecay);??
  • ????for?(int?k?=?0;k?<length0;++k)??
  • ????{??
  • ????????r[k]=?(r[k]+p[k])*rho0-g_table[(int)g[k]];??
  • ????}??
  • ????m?=?0;??
  • ????for?(int?k1=0;k1<width;++k1)??
  • ????{??
  • ????????int?n?=?k1;??
  • ????????for?(int?k2?=0;k2<height;++k2)??
  • ????????{??
  • ????????????data[n]?=?r[m++];??
  • ????????????n?+=?width;??
  • ????????}??
  • ????}??
  • ????memcpy(p,data,?sizeof(double)?*?length0);??
  • ????memcpy(r,data,?sizeof(double)?*?length0);??
  • ????for?(int?k2?=?0;?k2<height;++k2)??
  • ????{??
  • ??
  • ????????int?startIndex=k2?*?width;??
  • ????????double?mu?=?0.0;??
  • ????????for?(int?k=startIndex+1,?K=startIndex+width;k<K;++k)??
  • ????????{??
  • ????????????int?div0=fabs(p[k]-p[k-1]);??
  • ????????????mu?=exp_table[div0];??
  • ????????????p[k]?=?p[k?-?1]?*?mu?+?p[k]?*?(1.0?-?mu);??
  • ????????}??
  • ????????for?(int?k=startIndex+width-2;startIndex<=k;--k)??
  • ????????{??
  • ????????????int?div0=fabs(r[k]-r[k+1]);??
  • ????????????mu?=exp_table[div0];??
  • ????????????r[k]?=?r[k?+?1]?*?mu?+?r[k]?*?(1.0?-?mu)?;??
  • ????????}??
  • ????}??
  • ??
  • ????double?init_gain_mu=spatialDecay/(2-spatialDecay);??
  • ????for?(int?k?=?0;?k?<length0;?k++)??
  • ????{??
  • ????????data[k]=(p[k]+r[k])*rho0-data[k]*init_gain_mu;//文獻中的公式5??
  • ????}??
  • ????delete?p;??
  • ????delete?r;??
  • ????delete?g;??
  • }??
  • //水平方向遞歸??
  • void?CBeeps::runHorizontalVertical(double?*data,int?width,int?height,double?spatialDecay,double?*exptable,double?*g_table)??
  • {??
  • ????int?length=width*height;??
  • ????double*?g?=?new?double[length];??
  • ????double*?p?=?new?double[length];??
  • ????double*?r?=?new?double[length];??
  • ????memcpy(p,data,?sizeof(double)?*?length);??
  • ????memcpy(r,data,?sizeof(double)?*?length);??
  • ????double?rho0=1.0/(2-spatialDecay);??
  • ????for?(int?k2?=?0;k2?<?height;++k2)??
  • ????{??
  • ????????int?startIndex=k2?*?width;??
  • ????????for?(int?k=startIndex+1,K=startIndex+width;k<K;++k)??
  • ????????{??
  • ????????????int?div0=fabs(p[k]-p[k-1]);??
  • ????????????double?mu?=exptable[div0];??
  • ????????????p[k]?=?p[k?-?1]?*?mu?+?p[k]?*?(1.0?-?mu);//文獻公式1??
  • ??
  • ????????}??
  • ????????for?(int?k?=startIndex?+?width?-?2;startIndex?<=?k;--k)??
  • ????????{??
  • ????????????int?div0=fabs(r[k]-r[k+1]);??
  • ????????????double?mu?=exptable[div0];??
  • ????????????r[k]?=?r[k?+?1]?*?mu?+?r[k]?*?(1.0?-?mu);//文獻公式3??
  • ????????}??
  • ????????for?(int?k?=startIndex,K=startIndex+width;k<K;k++)??
  • ????????{??
  • ????????????r[k]=(r[k]+p[k])*rho0-?g_table[(int)data[k]];??
  • ????????}??
  • ????}??
  • ??????
  • ??
  • ????int?m?=?0;??
  • ????for?(int?k2=0;k2<height;k2++)??
  • ????{??
  • ????????int?n?=?k2;??
  • ????????for?(int?k1=0;k1<width;k1++)??
  • ????????{??
  • ????????????g[n]?=?r[m++];??
  • ????????????n?+=?height;??
  • ????????}??
  • ????}??
  • ????memcpy(p,?g,?sizeof(double)?*?height?*?width);??
  • ????memcpy(r,?g,?sizeof(double)?*?height?*?width);??
  • ????for?(int?k1=0;k1<width;++k1)??
  • ????{??
  • ????????int?startIndex=k1?*?height;??
  • ????????double?mu?=?0.0;??
  • ????????for?(int?k?=startIndex+1,K?=startIndex+height;k<K;++k)??
  • ????????{??
  • ????????????int?div0=fabs(p[k]-p[k-1]);??
  • ????????????mu?=exptable[div0];??
  • ????????????p[k]?=?p[k?-?1]?*?mu?+?p[k]?*?(1.0?-?mu);??
  • ????????}??
  • ????????for?(int?k=startIndex+height-2;startIndex<=k;--k)??
  • ????????{??
  • ????????????int?div0=fabs(r[k]-r[k+1]);??
  • ????????????mu?=exptable[div0];??
  • ????????????r[k]?=?r[k?+?1]?*?mu?+?r[k]?*?(1.0?-?mu);??
  • ????????}??
  • ????}??
  • ??
  • ??
  • ??
  • ????double?init_gain_mu=spatialDecay/(2-spatialDecay);??
  • ????for?(int?k?=?0;k?<length;++k)??
  • ????{??
  • ????????r[k]=?(r[k]+p[k])*rho0-?g[k]*init_gain_mu;??
  • ????}??
  • ????m?=?0;??
  • ????for?(int?k1=0;k1<width;++k1)??
  • ????{??
  • ????????int?n?=?k1;??
  • ????????for?(int?k2=0;k2<height;++k2)??
  • ????????{??
  • ????????????data[n]=r[m++];??
  • ????????????n?+=?width;??
  • ????????}??
  • ????}??
  • ????delete?p;??
  • ????delete?r;??
  • ????delete?g;??
  • }??


  • 最后看一下我用這個算法,實現磨皮的結果:


    原圖


    美圖秀秀磨皮結果


    雙指數遞歸算法磨皮結果

    本文地址:http://blog.csdn.net/hjimce/article/details/45420965?? ?作者:hjimce ? ? 聯系qq:1393852684 ? ??更多資源請關注我的博客:http://blog.csdn.net/hjimce?? ? ? ? ? ? ? ? ?原創文章,版權所有,轉載請保留這兩行作者信息

    總結

    以上是生活随笔為你收集整理的图像处理(五)双指数磨皮的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。