资讯详情

opencv 图像去噪学习总结

OpenCV图像处理部分图像平滑

图像平滑算法 程序分析及结果 图像平滑算法 平滑图像和模糊图像是同一个概念,主要用于去噪图像。为了不改变图像的相位信息,应使用滤波器进行平滑, 线性滤波器的统一形式如下: 其中h称为滤波器的核函数,说白了就是权值。不同的核函数代表不同的滤波器,有不同的用途。 在图像处理中,常见的滤波器包括: 归一化滤波器(Homogeneous blur) 也是平均过滤器,用输出像素点核窗口中的平均像素代替输出点像素值。 高斯滤波器(Guassian blur) 它是实际上最常用的滤波器。高斯滤波器是输入数组的每个像素点和 高斯内核 卷积作为输出 素值。高斯核相当于给输出像素的邻域不同的权值,输出像素点的权值最大(对应高斯函数 均值位置)。二维高斯函数为, 中值滤波器(median blur) 中值滤波用邻域(以当前像素为中心的正方形区域)像素的中值代替图像的每个像素。椒盐噪声最有效 去除跳变点的滤波器非常有效。 双边滤波器(Bilatrial blur) 在这种情况下,使用双边滤波器,以避免滤波器平滑图像去噪,模糊边缘。双边滤波器的解释参考 见http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html 下面的程序将先给标准Lena图像添加椒盐噪声,分别使用4种不同的滤波器进行平滑操作,请注意观察不 同滤波器对椒盐噪声的去噪效果! 程序分析及结果 /*  * FileName : image_smoothing.cpp  * Author   : xiahouzuoxin @163.com  * Version  : v1.0  * Date     : Wed 17 Sep 2014 08:30:25 PM CST  * Brief    :   *   * Copyright (C) MICL,USTB  */ #include "cv.h" #include "imgproc/imgproc.hpp" #include "highgui/highgui.hpp" using namespace std; using namespace cv; const int MAX_KERNEL_LENGTH = 10; const char *wn_name = "Smoothing"; static void salt(Mat &I, int n); static void disp_caption(const char *wn_name, Mat src, const char *caption); static void disp_image(const char *wn_name, Mat I); /*  * @brief     * @inputs    * @outputs   * @retval    */ int main(int argc, char *argv[]) {     if (argc<2) {         cout<<"Usage: ./image_smoothing [file name]"<<endl;         return -1;     }     Mat I = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);     salt(I, 6000);     imshow(wn_name, I);     waitKey(0);     Mat dst;  // Result     /* Homogeneous blur */     disp_caption(wn_name, I, "Homogeneous blur");     for (int i=1; i<MAX_KERNEL_LENGTH; i+=2) {         blur(I, dst, Size(i, i), Point(-1,-1));         disp_image(wn_name, dst);     }     /* Guassian blur */     disp_caption(wn_name, I, "Gaussian blur");     for (int i=1; i<MAX_KERNEL_LENGTH; i+=2) {         GaussianBlur(I, dst, Size(i, i), 0, 0);         disp_image(wn_name, dst);     }     /* Median blur */     disp_caption(wn_name, I, "Median blur");     for (int i=1; i<MAX_KERNEL_LENGTH; i+=2) {         medianBlur(I, dst, i);         disp_image(wn_name, dst);     }     /* Bilatrial blur */     disp_caption(wn_name, I, "Bilatrial blur");     for (int i=1; i<MAX_KERNEL_LENGTH; i+=2) {         bilateralFilter(I, dst, i, i*2, i/2);         disp_image(wn_name, dst);     }     waitKey(0);     return 0; } /*  * @brief   显示提示文字(滤波方法)  * @inputs    * @outputs   * @retval    */ static void disp_caption(const char *wn_name, Mat src, const char *caption) {     Mat dst = Mat::zeros(src.size(), src.type());     putText(dst, caption, Point(src.cols/4, src.rows/2), CV_FONT_HERSHEY_COMPLEX, 1, Scalar (255,255,255));     imshow(wn_name, dst);     waitKey(0); } /*  * @brief   显示图像  * @inputs    * @outputs   * @retval    */ static void disp_image(const char *wn_name, Mat I) {     imshow(wn_name, I);     waitKey(1000); } /*  * @brief   添加椒盐噪声  * @inputs    * @outputs   * @retval    */ static void salt(Mat &I, int n=3000) {     for (int k=0; k<n; k++) {         int i = rand() % I.cols;         int j = rand() % I.rows;         if (I.channels()) {             I.at<uchar>(j,i) = 255;         } else {             I.at<Vec3b>(j,i)[0] = 255;             I.at<Vec3b>(j,i)[1] = 255;             I.at<Vec3b>(j,i)[2] = 255;         }     } } 上面程序的逻辑非常清晰: 读入灰度图,并添加椒盐噪声(6000个噪声点): Mat I = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE); salt(I, 6000); LenaNoise disp_caption和disp_image函数分别是用于显示提示文字和平滑过程中的变化图像的,平滑过程中图像的 变化如下图: blur 注意观察上面的图,中值滤波(Median Blur)对椒盐噪声的效果最好! 四种滤波方法分别使用到4个OpenCV函数,这些函数的声明都在imgproc.hpp中,这些函数的前2个参数都 是原图像和滤波后图像。 归一化滤波器blur的第3个参数为滤波核窗口的大小,Size(i,i)表示ixi大小的窗口。 高斯滤波器GaussianBlur第3个参数也是滤波核窗口的大小,第4、第5个参数分辨表示x方向和y方向的δ 。 中值滤波器medianBlur第3个参数是滤波器的长度,该滤波器的窗口为正方形。 双边滤波器的函数原型如下: //! smooths the image using bilateral filter CV_EXPORTS_W void bilateralFilter( InputArray src, OutputArray dst, int d,                              double sigmaColor, double sigmaSpace,                              int borderType=BORDER_DEFAULT ); 本程序使用的Makefile文件为:  TARG=image_smoothing  SRC=image_smoothing.cpp  LIB=-L/usr/local/lib/  INC=-I/usr/local/include/opencv/ -I/usr/local/include/opencv2  CFLAGS=  $(TARG):$(SRC)      g++ -g -o $@ ${CFLAGS} $(LIB) $(INC) \          -lopencv_core -lopencv_highgui -lopencv_imgproc \          $^  .PHONY:clean  clean:      -rm $(TARG) tags -f ========

图像代数运算:平均值去噪,减去背景

代数运算,就是对两幅图像的点之间进行加、减、乘、除的运算。四种运算相应的公式为: 代数运算中比较常用的是图像相加和相减。图像相加常用来求平均值去除addtive噪声或者实现二次曝光 (double-exposure)。图像相减用于减去背景或周期噪声,污染等。 图像相加 OpenCV中提供了相加的函数 void cvAcc(               const CvArr* image,//输入图像              CvArr* sum,  //累积图像               const CvArr* mask=NULL//可选的运算    );   我们还需要用到一个线性变换转换函数来对相加的结果求平均 void cvConvertScale(            const CvArr* src, //输入数组           CvArr* dst,//输出数组           double scale=1,//比例           double shift=0 //缩放比例,可选   );   #define cvCvtScale cvConvertScale   #define cvScale  cvConvertScale   #define cvConvert( src, dst )  cvConvertScale( (src), (dst), 1, 0 )   实践:平均值去噪 我们用NASA的一段幸运团的视频做实验,截取视频的某几个连续帧求平均值: int main()   {       CvCapture* capture=cvCaptureFromFile("media.avi");       IplImage* frame=  NULL;       IplImage * imgsum =NULL;              int start=301;       int end=304;       cvSetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES, start);              int count = start;       while( cvGrabFrame(capture) && count <= end )       {           frame = cvRetrieveFrame(capture);// 获取当前帧           if(imgsum==NULL){               imgsum=cvCreateImage(cvGetSize(frame),IPL_DEPTH_32F,3);               cvZero(imgsum);           }           cvAcc(frame,imgsum);              char testname[100];           sprintf(testname,"%s%d%s","image",count,".jpg");           cvShowImage(testname,frame);           cvSaveImage(testname,frame);                      count++;       }       IplImage * imgavg = cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,3);       cvConvertScale(imgsum,imgavg,1.0/4.0);              cvShowImage("imageavg",imgavg);       cvSaveImage("imageavg_4.jpg",imgavg);              cvWaitKey(0);       cvReleaseCapture(&capture);       return 0;   }   以下从左到右分别是连续两帧、四帧、八帧、十六帧求均值的结果:     实践:图像二次曝光 曝光和去噪是一样的,也是对几幅图像求平均 //通过求平均二次曝光   int main()   {       IplImage* image1=  cvLoadImage("psu3.jpg");       IplImage* image2=  cvLoadImage("psu4.jpg");              IplImage * imgsum =cvCreateImage(cvGetSize(image1),IPL_DEPTH_32F,3);       cvZero(imgsum);       cvAcc(image1,imgsum);       cvAcc(image2,imgsum);          IplImage * imgavg = cvCreateImage(cvGetSize(image1),IPL_DEPTH_8U,3);       cvConvertScale(imgsum,imgavg,1.0/2.0);          cvShowImage("imageavg",imgavg);       cvSaveImage("avg.jpg",imgavg);          cvWaitKey(0);       cvReleaseImage(&image1);       cvReleaseImage(&image2);       cvReleaseImage(&imgsum);       cvReleaseImage(&imgavg);       return 0;   }   下图是对同学街舞截图的“二次曝光”效果: 图像相减 OpenCV中用cvAbsDiff函数计算两数组的差的绝对值 void cvAbsDiff(            const CvArr* src1,//第一个输入数组           const CvArr* src2,//第二个输入数组           CvArr* dst//输出数组   );   实践:减去背景 减去背景是通过两幅图像代数相减,可以判断出前景区域和运动区域,这是最简单(很多时候也是效果很 好的)运动检测方法。 //减去背景   int main()   {       IplImage* pFrame = NULL;        IplImage* pFrImg = NULL;       IplImage* pBkImg = NULL;          CvMat* pFrameMat = NULL;       CvMat* pFrMat = NULL;       CvMat* pBkMat = NULL;          CvCapture* pCapture = NULL;          int nFrmNum = 0;          //创建窗口       cvNamedWindow("video", 1);       cvNamedWindow("background",1);       cvNamedWindow("foreground",1);          pCapture = cvCaptureFromFile("media.avi");       while(pFrame = cvQueryFrame( pCapture ))       {           nFrmNum++;              //如果是第一帧,需要申请内存,并初始化           if(nFrmNum == 1)           {               pBkImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);               pFrImg = cvCreateImage(cvSize(pFrame->width, pFrame->height),  IPL_DEPTH_8U,1);                  pBkMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);               pFrMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);               pFrameMat = cvCreateMat(pFrame->height, pFrame->width, CV_32FC1);                  //转化成单通道图像再处理               cvCvtColor(pFrame, pBkImg, CV_BGR2GRAY);               cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);  

标签: ibp传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台