Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

It's not clear what do you mean by sorting, but looking at your code, it seems you want to find the median value of the pixels in an image. So I will answer this question.

For unsigned char matrices (normal images, or in OpenCV format CV_8UC[1,2,3]), you can use an old, but fery fast trick: a histogram.

  • Calculate the histogram of your image
  • For each channel, start to sum the elements in the bins until their count is equal or above half the number of pixels in the image. The bin where you stop is the median element of your image

    cv:Mat hist = cv::calcHist(image);
    
    uchar * h = hist.data;    
    int sum = 0, bin = 0;
    int maxElements = image.total();
    
    while(sum < maxElements && bin < 255)
    {
       sum += h[bin];
    }
    
    std::cout << "Median pixel value of the image is " << bin << std::endl;
    

Because it does no sorting at all, and no copies of the original data, it is a lot faster than any other median-extraction algorithm.

I did not test the code, and it probably needs some checks, but you get the idea.

And if you want to sort a matrix of arbitrary data type, you should look into the sort functions provided by OpenCV. Check the docs :)

It's not clear what do you mean by sorting, but looking at your code, it seems you want to find the median value of the pixels in an image. So I will answer this question.

For unsigned char matrices (normal images, or in OpenCV format CV_8UC[1,2,3]), you can use an old, but fery fast trick: a histogram.

  • Calculate the histogram of your image
  • For each channel, start to sum the elements in the bins until their count is equal or above half the number of pixels in the image. The bin where you stop is the median element of your image

    cv:Mat hist = cv::calcHist(image);
    
    uchar * h = hist.data;    
    int sum = 0, bin = 0;
    int maxElements = image.total();
    
    while(sum while((sum < maxElements maxElements) && bin (bin < 255)
    255))
    {
       sum += h[bin];
    }
    
    std::cout << "Median pixel value of the image is " << bin << std::endl;
    

Because it does no sorting at all, and no copies of the original data, it is a lot faster than any other median-extraction algorithm.

I did not test the code, and it probably needs some checks, but you get the idea.

And if you want to sort a matrix of arbitrary data type, you should look into the sort functions provided by OpenCV. Check the docs :)

It's not clear what do you mean by sorting, but looking at your code, it seems you want to find the median value of the pixels in an image. So I will answer this question.

For unsigned char matrices (normal images, or in OpenCV format CV_8UC[1,2,3]), you can use an old, but fery fast trick: a histogram.

  • Calculate the histogram of your image
  • For each channel, start to sum the elements in the bins until their count is equal or above half the number of pixels in the image. The bin where you stop is the median element of your image

    cv:Mat hist = cv::calcHist(image);
    
    uchar * h = hist.data;    
    int sum = 0, bin = 0;
    int maxElements = image.total();
    
    while((sum < maxElements) && (bin < 255))
    {
       sum += h[bin];
    }
    
    std::cout << "Median pixel value of the image is " << bin << std::endl;
    

Because it does no sorting at all, and no copies of the original data, it is a lot faster than any other median-extraction algorithm.

I did not test the code, and it probably needs some checks, but you get the idea.

And if you want to sort a matrix of arbitrary data type, you should look into the sort functions provided by OpenCV. Check the docs :)

EDIT: there is an internal function getMedian in align.cpp

//enum { LDR_SIZE = 256 };
int getMedian(Mat& img)
{
    int channels = 0;
    Mat hist;
    int hist_size = LDR_SIZE;
    float range[] = {0, LDR_SIZE} ;
    const float* ranges[] = {range};
    calcHist(&img, 1, &channels, Mat(), hist, 1, &hist_size, ranges);
    float *ptr = hist.ptr<float>();
    int median = 0, sum = 0;
    int thresh = (int)img.total() / 2;
    while(sum < thresh && median < LDR_SIZE) {
        sum += static_cast<int>(ptr[median]);
        median++;
    }
    return median;
}