1. 程式人生 > >opencv 影象去噪學習總結

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 [email protected] ${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);  

            cvConvert(pFrImg, pFrameMat);  
            cvConvert(pFrImg, pFrMat);  
            cvConvert(pFrImg, pBkMat);  
        }  
        else  
        {  
            cvCvtColor(pFrame, pFrImg, CV_BGR2GRAY);  
            cvConvert(pFrImg, pFrameMat);  
            //當前幀跟背景圖相減  
            cvAbsDiff(pFrameMat, pBkMat, pFrMat);  
            //二值化前景圖  
            cvThreshold(pFrMat, pFrImg, 60, 255.0, CV_THRESH_BINARY);  
            //更新背景  
            cvRunningAvg(pFrameMat, pBkMat, 0.003, 0);  
            //將背景轉化為影象格式,用以顯示  
            cvConvert(pBkMat, pBkImg);  

            cvShowImage("video", pFrame);  
            cvShowImage("background", pBkImg);  
            cvShowImage("foreground", pFrImg);  

            if( cvWaitKey(2) >= 0 )  
                break;  
        }  
    }  
    cvDestroyWindow("video");  
    cvDestroyWindow("background");  
    cvDestroyWindow("foreground");  
    cvReleaseImage(&pFrImg);  
    cvReleaseImage(&pBkImg);  
    cvReleaseMat(&pFrameMat);  
    cvReleaseMat(&pFrMat);  
    cvReleaseMat(&pBkMat);  
    cvReleaseCapture(&pCapture);  
    return 0;  
}  
效果圖:


========


opencv連通域去噪  



相關推薦

opencv 影象學習總結

OpenCV影象處理篇之影象平滑影象平滑演算法程式分析及結果影象平滑演算法影象平滑與影象模糊是同一概念,主要用於影象的去噪。平滑要使用濾波器,為不改變影象的相位資訊,一般使用線性濾波器,其統一形式如下:其中h稱為濾波器的核函式,說白了就是權值。不同的核函式代表不同的濾波器,有

基於深度學習影象(論文總結

2015 深度學習、自編碼器、低照度影象增強 Lore, Kin Gwn, Adedotun Akintayo, and Soumik Sarkar. "LLNet: A Deep Autoencoder Approach to Natural Low-light Image Enhancement." ar

學習 python_opencv影象筆記

最近一直在跟OpenCV-Python 中文教程學習,在學到使用 cv2.fastNlMeansDenoisingColored()函式去噪時,在使用教程程式碼時發現結果不一樣,原始碼如下: import numpy as np import cv2 from matplotlib i

傅立葉變換及其在opencv影象的實現

前言 我保證這篇文章和你以前看過的所有文章都不同,這是12年還在果殼的時候寫的,但是當時沒有來得及寫 完就出國了……於是拖了兩年,嗯,我是拖延症患者…… 這篇文章的核心思想就是: 要讓讀者在不看任何數學公式的情況下理解傅立葉分析。 傅立葉分析不僅僅是一個數學工

深度學習結合非區域性均值濾波的影象演算法

其實這是半年之前完成的內容,一直懶著沒有總結,今天看了看程式碼,發覺再不總結自己以後都看不懂了,故整理如下。 非區域性均值是一種基於塊匹配來確定濾波權值的。即先確定一個塊的大小,例如7x7,然後在確定一個搜尋區域,例如15x15,在15x15這個搜尋區域中的每一個點,計算7

OpenCV單kinect多幀靜止場景的深度影象

老闆kinect去噪的任務下達已經有半個多月了,前期除了看了幾天文獻之外就打醬油了,好像每天都很忙,可是就是不知道在忙什麼。這幾天為了交差,就胡亂湊了幾段程式碼,得到一個結果,也知道不行,先應付一下,再圖打算。 程式思想很簡單,先對靜止的場景連續取樣若干幀,然後對所有點在時間域取中值,對取完中值之後的無效點

基於深度學習影象暨SRMD論文閱讀筆記

最近一直在做基於卷積神經網路的影象去噪~感覺資料比較凌亂,本博文就是整理好經典的論文材料~ 同時本博文也結合了閱讀論文《Learning a Single Convolutional Super-Resolution Network for Multiple Degradations》時的心

基於字典學習影象研究與實踐

機器學習在影象處理中有非常多的應用,運用機器學習(包括現在非常流行的深度學習)技術,很多傳統的影象處理問題都會取得相當不錯的效果。今天我們就以機器學習中的字典學習(Dictionary Learning)為例,來展示其在影象去噪方面的應用。文中程式碼採用Python寫成,其中

基於圖學習影象(二)——圖學習演算法

3.圖學習在影象降噪中的經典演算法 3.1 Perturbation of the Eigenvectors of the Graph Laplacian: Application to Image

一種基於凸優化的影象方法演示

本文介紹一種基於凸優化的影象去噪方法。 該方法採用L1範數來衡量影象的平滑度,即能濾除澡聲,又能最大限度地儲存影象的邊緣。 模型如下:   其中f(x)為差分矩陣,存放了X每個元素與其4鄰域的差值。 I為輸入的灰度影象。 對於三通道彩色影象,可

opencv影象點訪問學習筆記

注意opencv資料型別 關於uchar,首先了解unsigned和signed區別(這裡暫時沒有太搞明白,存疑。本質在於二進位制的儲存方式) https://blog.csdn.net/gukesdo/article/details/6909766 http://www.cnblog

影象處理之影象

假設影象退化過程被建模為一個退化函式和一個加性噪聲項,對輸入影象f(x,y)進行處理,產生退化後的影象g(x,y)。給定g(x,y)和退化函式H以及關於加性噪聲項的一些知識,影象復原的目的就是獲得原始影象的一個估計。 空間域的退化影象: 其中h(x,y)是退化函式的空

基於深度卷積神經網路(D-CNN)的影象方法

基於深度卷積神經網路的影象去噪方法   摘要:影象去噪在影象處理中仍然是一個具有挑戰性的問題。作者提出了一種基於深度卷積神經網路(DCNN)的影象去噪方法。作者設計的不同於其他基於學習的方法:一個DCNN來實現噪聲影象。因此,通過從汙染影象中分離噪聲影

DenoisingAutoencoder(影象自動編碼器)

本文主要介紹使用TensorFlow實現DenoisingAutoencoder(影象去噪自動編碼器)。 下面是示例程式碼: # 匯入相關模組 import numpy as np import sys import tensorflow as tf import matplotlib.

matlab中使用小波變換進行影象

1:基於小波變換摸極大值原理 2:基於小波變換系數的相關性 3:基於小波閾值的去噪。 基於小波閾值的去噪方法3個步驟: 1: 計算含噪聲影象的小波變換。選擇合適的小波基和小波分解層數J,運用Matlab 分解演算法將含有噪聲影象進行J層小波分解,得到相應的小波分解係數。 2:對分解後的高頻係數進行閾值量化

Nonlocal-Means 演算法影象

非區域性均值去噪演算法其實很簡單,該種去噪方法和高斯去噪和雙邊濾波器去噪很像,都是利用一些準則,通過“周圍”的畫素點加權估計畫素點的真實值,如下圖所示: 最左邊一副圖表示Gauss濾波的特點,就是利用影象畫素點相近的程度來估計權重,中間幅圖表示雙邊濾波器在考慮畫素點本身取值

【matlab】影象的程式碼測試

%% 自己設定頻域的濾波視窗 girl=imread('F:\Users\*****\Pictures\CGS_stripe1.bmp'); girl=rgb2gray(girl); girl=im2double(girl); subplot(1,2,1);imshow(girl);%顯示原

影象及其實現

影象去噪處理方法可分以下兩大類:{空間域法:變換域法:在原圖像上直接進行數據運算,對像素的灰度值進行處理在圖像的變換域上處理,對變換後的系數進行相應處理,再反變換達到去噪的目的{空間域法:在原影象上直接進行資料運算,對畫素的灰度值進行處理變換域法:在影象的變換域

影象處理】【影象模糊】 總結

本人最近由於做相關去卷積工作,查閱了上百篇文獻,發現在這個領域,可能也是‘水太深’了,並沒有一篇較好的綜述,現在做以下總結---- 只對高斯與散焦模糊的非盲去卷積領域,對於運動模糊並未做總結,但實際上除了點擴散函式的估計有區別,實際上這三類去模糊甚至和去噪,損失函式模型都可

Non local means影象演算法及其實現

論文原文:A non-local algorithm for image denoising 該文章2005由Buades等人發表在CVPR上,對於single-image denoise來說,當時基本上是state-of-the-art。 去噪屬於影象復原的範疇,通常使