0

I tried to google a lot but could not find any C++ code to generate noisy image with poisson and speckle noise. Although, I got a code in python and tried to convert it into C++. https://stackoverflow.com/a/30624520/3465857 Please have a look, I am not sure if it is correctly done or not.

  Mat& addPoissonNoiseIntoImage(Mat& src){
        unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
        static Mat noisyImg = src.clone();
        std::default_random_engine generator (seed);
        std::vector<float> uniqueValsOfMat = BasicAlgo::getInstance()->uniqueValuesInMat(src);
        unsigned long int val = uniqueValsOfMat.size();
        float vals = pow(2, (ceil(log2(val))));
        for(int i = 0; i < src.rows; i++)
        {
            for(int j = 0; j < src.cols; j++){
                float pixelVal = (double)(src.at<uchar>(i,j));
                pixelVal = pixelVal * vals;
                std::poisson_distribution<int> distribution (pixelVal);
                float generatedVal = distribution(generator) / float(vals);
                noisyImg.at<uchar>(i,j) = generatedVal;
            }
        }
        return noisyImg;
    }

    Mat& addSpeckleNoiseIntoImage(Mat& src, float mean, float std ){
        unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
        static Mat noisyImg = src.clone();
        std::default_random_engine generator (seed);
        std::normal_distribution<double> distribution (mean,std);
        for(int i = 0; i < src.rows; i++)
        {
            for(int j = 0; j < src.cols; j++){
                float pixelVal = (double)(src.at<uchar>(i,j));
                while(true){
                    float vals = distribution(generator);
                    pixelVal = pixelVal + pixelVal * vals;
                    if( (pixelVal > 0) && (pixelVal < 256) )
                        break; // you got the right pixel value, so break
                }
                noisyImg.at<uchar>(i,j) = pixelVal;
            }
        }
        return noisyImg;
    }

For finding the unique values in Mat:

  std::vector<float> uniqueValuesInMat(const cv::Mat& rawData, bool sort = false)
    {
        Mat input;
        rawData.convertTo(input, CV_32F);
        if (input.channels() > 1 || input.type() != CV_32F)
        {
            std::cerr << "unique !!! Only works with CV_32F 1-channel Mat" << std::endl;
            return std::vector<float>();
        }

        std::vector<float> out;
        for (int y = 0; y < input.rows; ++y)
        {
            const float* row_ptr = input.ptr<float>(y);
            for (int x = 0; x < input.cols; ++x)
            {
                float value = row_ptr[x];

                if ( std::find(out.begin(), out.end(), value) == out.end() )
                    out.push_back(value);
            }
        }

        if (sort)
            std::sort(out.begin(), out.end());

        return out;
    }

I am not sure, whether the code for generating poisson and speckle noise is correctly done or not. Please have a look.

Tanmoy Mondal
  • 449
  • 1
  • 6
  • 12
  • What's the point of returning references to a static `cv::Mat` in each function? – Dan Mašek Dec 31 '17 at 14:39
  • Add noise to an image with a constant grey value, then compute statistics on the output. Does it match Poisson statistics? If yes, you wrote it right. If no, you didn't. – Cris Luengo Dec 31 '17 at 16:09

0 Answers0