之前有寫過一篇關於OpenCV像素取/存值的方式[1]

彩色像素取值

image.at<cv::Vec3b>(row, col)[0]

image.at<cv::Vec3b>(row, col)[1]

image.at<cv::Vec3b>(row, col)[2]

灰階像素取值

image.at<uchar>(row, col) = 255;

加上另一篇[2] 利用C# 拉UI並傳參數給OpenCV C++ DLL

規劃如下:

C# 公開函數:

UI只需要傳入雜訊點數(numPts),

對使用者來說並不需要知道用哪一個Mat影像資料(這部分由C++實作)

C++私有函數:

針對圖像資料(image), 加入指定的雜訊點數(numPts),

該點數則C#公開函數傳來

宣告imageProcLib.hpp

image

實作imageProcLib.cpp

//----------------------------------------------------------------
void ImageProc::AddNoise(int numPts)
{
    imgDst = img.clone();
    AddNoise(imgDst, numPts);
}
void ImageProc::AddNoise(Mat image, int numPts)
{
    int i, row, col;
    if(image.channels() == 3)    // 彩色
    {
        for(i=0; i<numPts; i++)
        {
            row = rand() % image.rows;
            col = rand() % image.cols;
            image.at<cv::Vec3b>(row, col)[0] = 255;
            image.at<cv::Vec3b>(row, col)[1] = 255;
            image.at<cv::Vec3b>(row, col)[2] = 255;
        }
    }else                       // 灰階 
    {
        for(i=0; i<numPts; i++)
        {
            row = rand() % image.rows;
            col = rand() % image.cols;
            image.at<uchar>(row, col) = 255;
        }
    }
}
//----------------------------------------------------------------

=====================================================================

C# GUI如下

image

為了怕使用者未先載入圖像所以加入讀取檔案是否成功

imageProcLib.hpp

bool ImageProc::IsImgLoaded();                  // 檢查讀取檔案是否成功

imageProcLib.cpp

bool ImageProc::IsImgLoaded()                          // 檢查讀取檔案是否成功
{
    return (!img.data);
}

C# UI選取一張照片, 然後傳入雜訊點數並顯示結果影像

private void openToolStripMenuItem_Click(object sender, EventArgs e)
      {
          using (OpenFileDialog ofd = new OpenFileDialog())
          {
              if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
              {
                  unsafe
                  {
                      fixed (char* filename = ofd.FileName)
                      {
                          imgProc.imread(filename);
                          int numPts = Convert.ToInt16(numericUpDown1.Value);
                          if (!imgProc.IsImgLoaded())              // 檢查讀取檔案是否成功
                          {
                              imgProc.AddNoise(numPts);            // 加入雜訊點數
                              imgProc.showImage();                 // 顯示影像
                          }
                      }
                  }
 
              }
          }
      }
 
      // 動態更新
      private void numericUpDown1_ValueChanged(object sender, EventArgs e)
      {
             int numPts = Convert.ToInt16(numericUpDown1.Value);
             try
             {
                 if (!imgProc.IsImgLoaded())           // 檢查讀取檔案是否成功
                 {
                     imgProc.AddNoise(numPts);         // 加入雜訊點數
                     imgProc.showImage();              // 顯示影像
                 }
                 else
                 {
                     MessageBox.Show("請先載入一張照片");
                 }
             }
             catch (Exception ex)
             {
                 MessageBox.Show(ex.Message);
             }        
      }

測試如下

image

image

===================================================================

接下來, 練習[3] normally distributed random numbers (randn)

以下為原發問者問題描述節錄:

here's my problem: I'm trying to create a simple program which adds Gaussian noise to an input image. The only constraints are that the input image is of type CV_64F (i.e. double) and the values are and must be kept normalized between 0 and 1.

The code I wrote is the following:

Mat my_noise;
my_ noise = Mat (input.size(), input.type());

randn(noise, 0, 5); //mean and variance

input += noise;

The above code doesn't work, the resulting image doesn't get displayed properly. I think that happens because it gets out of the 0,1 range. I modified the code like this:

Mat my_noise;
my_ noise = Mat (input.size(), input.type());

randn(noise, 0, 5); //mean and variance

input += noise;

normalize(input, input, 0.0, 1.0, CV_MINMAX, CV_64F);

but it still doesn't work. Again, the resulting image doesn't get displayed properly. Where is the problem? Remember: the input image is of type CV_64F and the values are normalized between 0 and 1 before adding noise and have to remain like also after the noise addition.

=====================================================================

imageProcLib.hpp

void AddNoiseRandN();                           // 加入 normally distributed random numbers
void AddNoiseRandN(double mean, double std);

imageProcLib.cpp

//----------------------------------------------------------------
void ImageProc::AddNoiseRandN(double mean, double stddev)
{
    if(img.channels() == 3)
    {
        vector<Mat> spl;
        split(img, spl);
        noise = Mat(spl[0].size(), CV_64F);
        randn(noise, mean, stddev);
        
        for(int i=0; i<3; i++)
        {
            normalize(spl[i], spl[i], 0.0, 1.0, CV_MINMAX, CV_64F);
            spl[i] = spl[i] + noise;                       
         }
        merge(spl, imgDst);
 
    }
}
void ImageProc::AddNoiseRandN()                        // 加入 normally distributed random numbers
{
    AddNoiseRandN(0.0, 0.01); 
}

C# UI

image

private void randNToolStripMenuItem_Click(object sender, EventArgs e)
{
    double mean = Convert.ToDouble(textBox1.Text);
    double stddev = Convert.ToDouble(textBox2.Text);
    using (OpenFileDialog ofd = new OpenFileDialog())
    {
        if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
        {
            unsafe
            {
                fixed (char* filename = ofd.FileName)
                {
                    imgProc.imread(filename);
                    if (!imgProc.IsImgLoaded())              // 檢查讀取檔案是否成功
                    {
                        imgProc.AddNoiseRandN(mean, stddev);
                        imgProc.showImage();                 // 顯示影像
                    }
                }
            }
 
        }
    }
}

image

image

image

操作影片

參考資料

1. OpenCV 2.4.9 取得和設定彩色(灰階)影像的像素值

2. 利用C# 拉UI並傳參數給OpenCV C++ DLL

3. http://answers.opencv.org/question/36309/opencv-gaussian-noise/

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 me1237guy 的頭像
    me1237guy

    天天向上

    me1237guy 發表在 痞客邦 留言(0) 人氣()