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.