中值濾波C語言優化
圖像平滑是圖像預處理的基本操作,本文首先用不同的方法對一張圖片做預處理比較它們效果的不同,然后針對中值濾波,實現了一種快速實現.(其實是copy的opencv實現,呵呵).因為opencv的實現方法感覺太好了,今天就特別寫下來.既有備忘的作用,同時如果誰看到這篇文章,也可以借鑒下opencv的實現.
1 原始圖像
2 均值濾波圖像
3 中值濾波圖像
4 雙邊濾波圖像
5高斯濾波圖像
上圖的代碼
void CDialogTest2013Dlg::OnBnClickedMfcbutton1() { char file[10]="e:\\1.jpg";
IplImage *src = cvLoadImage(file,0); CvSize picSize; picSize.width = src->width; picSize.height = src->height;
IplImage *dst_midian= cvCreateImage(picSize,8,1); IplImage *dst_blur = cvCreateImage(picSize,8,1); IplImage *dst_gaussian = cvCreateImage(picSize,8,1); IplImage *dst_bilateral = cvCreateImage(picSize,8,1);
cvSmooth(src, dst_midian, CV_MEDIAN,3,3); cvSmooth(src, dst_blur, CV_BLUR,3,3); cvSmooth(src, dst_gaussian, CV_GAUSSIAN,3,3); cvSmooth(src, dst_bilateral, CV_BILATERAL,3,3);
} |
均值濾波原理:把一個點周圍點求均值,這個均值給這個點.
中值濾波原理:把一個點周圍的點排序,把中位數給這個點.
雙邊濾波原理:這個一句話說不清楚,可以看這個博文 http://blog.csdn.net/bugrunner/article/details/7170471
高斯濾波原理:均值濾波對一個點周圍點求和是每個點的權重都是1,高斯濾波的權重不是1了,是一個類似高斯分布的權重分布,距離目標點
近的地方權重高點,距離目標點遠的地方,權重低些.
中值濾波的opencv實現
template<class Op, class VecOp> staticvoid medianBlur_SortNet(const Mat& _src, Mat& _dst,int m ) { typedef typename Op::value_type T; typedef typename Op::arg_type WT; typedef typename VecOp::arg_type VT;
const T* src =(const T*)_src.data; T* dst =(T*)_dst.data; int sstep =(int)(_src.step/sizeof(T)); int dstep =(int)(_dst.step/sizeof(T)); Size size = _dst.size(); int i, j, k, cn = _src.channels(); Op op; VecOp vop; volatile bool useSIMD = checkHardwareSupport(CV_CPU_SSE2);
if( m ==3) { if( size.width ==1|| size.height ==1) { int len = size.width + size.height -1; int sdelta = size.height ==1? cn : sstep; int sdelta0 = size.height ==1?0: sstep - cn; int ddelta = size.height ==1? cn : dstep;
for( i =0; i < len; i++, src += sdelta0, dst += ddelta ) for( j =0; j < cn; j++, src++) { WT p0 = src[i >0?-sdelta :0]; WT p1 = src[0]; WT p2 = src[i < len -1? sdelta :0];
op(p0, p1); op(p1, p2); op(p0, p1); dst[j]=(T)p1; } return; }
size.width *= cn; for( i =0; i < size.height; i++, dst += dstep ) { const T* row0 = src + std::max(i -1,0)*sstep; const T* row1 = src + i*sstep; const T* row2 = src + std::min(i +1, size.height-1)*sstep; int limit = useSIMD ? cn : size.width;
for(j =0;;) { for(; j < limit; j++) { int j0 = j >= cn ? j - cn : j; int j2 = j < size.width - cn ? j + cn : j; WT p0 = row0[j0], p1 = row0[j], p2 = row0[j2]; WT p3 = row1[j0], p4 = row1[j], p5 = row1[j2]; WT p6 = row2[j0], p7 = row2[j], p8 = row2[j2];
op(p1, p2); op(p4, p5); op(p7, p8); op(p0, p1); //op(p1, p2) 交換p1和p2兩個數 op(p3, p4); op(p6, p7); op(p1, p2); op(p4, p5); op(p7, p8); op(p0, p3); op(p5, p8); op(p4, p7); op(p3, p6); op(p1, p4); op(p2, p5); op(p4, p7); op(p4, p2); op(p6, p4); op(p4, p2); dst[j]=(T)p4; }
if( limit == size.width ) break;
for(; j <= size.width - VecOp::SIZE - cn; j += VecOp::SIZE ) { VT p0 = vop.load(row0+j-cn), p1 = vop.load(row0+j), p2 = vop.load(row0+j+cn); VT p3 = vop.load(row1+j-cn), p4 = vop.load(row1+j), p5 = vop.load(row1+j+cn); VT p6 = vop.load(row2+j-cn), p7 = vop.load(row2+j), p8 = vop.load(row2+j+cn);
vop(p1, p2); vop(p4, p5); vop(p7, p8); vop(p0, p1); vop(p3, p4); vop(p6, p7); vop(p1, p2); vop(p4, p5); vop(p7, p8); vop(p0, p3); vop(p5, p8); vop(p4, p7); vop(p3, p6); vop(p1, p4); vop(p2, p5); vop(p4, p7); vop(p4, p2); vop(p6, p4); vop(p4, p2); vop.store(dst+j, p4); }
limit = size.width; } } } }
}
|