简体   繁体   中英

Mapping pixels/elements to percentiles (C++/OpenCV)

I am using OpenCV and I have the following problem I wish to solve on an image. However, my question doesn't have to be restricted to OpenCV if it is an issue, it could simply be more general c++ on, say, vectors.

The problem

I want to map the pixel values of an input image (or elements of an input vector) into an output image (or vector) of same size. Each element of the output should contain the percentile* of the corresponding element in the input.

My question is

How would I code an implementation of this problem? (In c++ or OpenCV)

Example

I will show an example of a one-dimensional image, just for simplicity.

Input: (1, 2, 10, 3, 4, 5, 6, 12, 7)

Output*: (0.11, 0.22, 0.89, 0.33, 0.44, 0.56, 0.67, 1.00, 0.78)

Performance?

I'm writing code for an analysis of images that may be a few hundred by a few hundred. I assume that my problem is possible in O(n log n), but I don't think even O(n^2) would be an issue (where n is the total number of elements in the image/vector). However, if precise percentiles cause too much issues with the complexity, I'm okay with having a certain number of bins instead.


(*) I know that there are a few different ways of conceptualizing percentile, whether you round up or down et cetera. This is of no importance to me. Whatever way works.

I am not sure it this is what you're looking for but this a naive implementation of percentile for image pixel values.

    cv::Mat image = cv::imread("image.jpg",cv::IMREAD_UNCHANGED);

    // convert image to gray
    cv::Mat gray;
    cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);

    // calculate histogram for every pixel value (i.e [0 - 255])
    cv::Mat hist;
    int histSize = 256;
    float range[] = { 0, 256 } ;
    const float* histRange = { range };
    bool uniform = true; bool accumulate = false;
    cv::calcHist( &gray, 1, 0, cv::Mat(), hist, 1, &histSize, &histRange, uniform, accumulate );

    // total pixels in image
    float totalPixels = gray.cols * gray.rows;

    // calculate percentage of every histogram bin (i.e: pixel value [0 - 255])
    // the 'bins' variable holds pairs of (int pixelValue, float percentage) 
    std::vector<std::pair<int, float>> bins;
    float percentage;
    for(int i = 0; i < 256; ++i)
    {
        percentage = (hist.at<float>(i,0)*100.0)/totalPixels;
        bins.push_back(std::make_pair(i, percentage));
    }

    // sort the bins according to percentage
    sort(bins.begin(), bins.end(),comparator());

    // compute percentile for a pixel value
    int pixel = 185;
    float sum = 0;

    for (auto b : bins)
    {
        if(b.first != pixel)
            sum += b.second;
        else
        {
            sum += b.second/2;
            break;
        }
    }

    std::cout<<"Percentile for pixel("<<pixel<<"): "<<sum<<std::endl;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM