برای اینکار کافیه هیستوگرام بگیرید و هیستوگرام را از 2 طرف پیمایش کنید معیاری که برای dynamic range در نظر می گیرن یه حد آستانه مشخص می کنند به فرض یک درصد به شرطی که توزیع تجمعی در bin جاری تا زمانیکه از آستانه در نظر گرفته شده کمتر باشه به پیمایش ادامه میدم تا به نقطه مورد نظر برسیم اینکار برای هر دوسمت هیستوگرام هم بخش بالا و پایین انجام میدم. به صورت زیر:
void get1DHistogram(cv::Mat src, MatND &hist, int size, cv::InputArray _mask)
{
int hist_size[] = { size };
float ranges1[] = { 0, float(size - 1) };
const float* ranges[] = { ranges1 };
int channels[] = { 0 };
calcHist(&src, 1, channels, _mask, hist, 1, hist_size, ranges);
}
void getDynamicRange2(cv::InputArray src, cv::InputArray mask_image, float low_percent, float high_percent, unsigned char& min_range, unsigned char& max_range)
{
MatND hist;
get1DHistogram(src.getMat(), hist, 256, mask_image.getMat());
int total_count;
if (!mask_image.empty())
total_count = countNonZero(mask_image);
else total_count = src.size().area();
int low_percent_count = cvRound(total_count * low_percent / 100.f);
int high_percent_count = cvRound(total_count * high_percent / 100.f);
int min_rng = 0;
float cur_count = 0;
int size = 256;
while ((min_rng < size) && (cur_count < low_percent_count))
{
cur_count += (hist.at<float>(min_rng) < 0) ? 0 : hist.at<float>(min_rng);
min_rng++;
}
int max_rng = size - 1;
cur_count = 0;
while ((max_rng >= 0) && (cur_count < high_percent_count))
{
cur_count += (hist.at<float>(max_rng) < 0) ? 0 : hist.at<float>(max_rng);
max_rng--;
}
if (min_rng > max_rng)
{
min_rng = max_rng;
}
min_range = min_rng;
max_range = max_rng;
}
جهت اعمال dynamic range جدید بر روی تصویر به این پست مراجعه کنید.