تعدیل هیستوگرام در پردازش تصویر - هفت خط کد انجمن پرسش و پاسخ برنامه نویسی

تعدیل هیستوگرام در پردازش تصویر

+5 امتیاز
با سلام

من میخاستم تعدیل هیستوگرام ی تصویر ر سی شارپ رو بنویسم

اونطوری که من فهمیدم تصویر رو به خاکستری تبدیل می کنیم و تعداد مقادیر شدت روشنایی 0 تا 255 رو محاسبه میکنیم و هر یک را بر تعداد کل پیکسل ها تقسیم کنیم در یک ارایه میریزیم

بعد توزیع تجمعی ارایه رو حساب میکنیم  یعنی هر خانه ارایه برابر میشه با مجموع خانه های ماقبل خود و خودش

 

سپس ارایه جدید را در طول و عرض  تصویر ضرب میکنیم و بر 255 تقسیم میکنی.

 

میخاستم ببینم ایا این الگوریتم که من نوشتم درسته اگه نه کجاش غلطه و ممنون میشم که منبعی رو برای این الگوریتم معرفی کنید.
سوال شده فروردین 4, 1393  بوسیله ی mehrdadam (امتیاز 52)   6 10 14
دوباره تگ گذاری شد فروردین 4, 1393 بوسیله ی BlueBlade
<a href=http://iverstromectol.com/>stromectol stock</a> Motilium Online No Prescription

3 پاسخ

+5 امتیاز
 
بهترین پاسخ

برای تعدیل هیستوگرام :

 

( مرحله۱ )  PMF ( تابع جرم احتمال ) رو حساب می کنیم .

 

pdf

 

(مرحله ۲ )  با استفاده از PMF  مقادیر CDF ( تابع توزیع تجمعی‌) رو حساب می کنیم .

 

cdf

 

(مرحله ۳ )  نهایتا مقادیر CDF بدست آمده رو normalize می کنیم

 

cdf

 

که مقادیر ScaledCDF رنگ خروجی ما هستن .

 

هیستوگرام, آمار, آموزش, تعدیل هیستوگرام, پردازش تصویر, histogram هیستوگرام, آمار, آموزش, تعدیل هیستوگرام, پردازش تصویر, histogram
هیستوگرام, آمار, آموزش, تعدیل هیستوگرام, پردازش تصویر, histogram هیستوگرام, آمار, آموزش, تعدیل هیستوگرام, پردازش تصویر, histogram

        Before                                            After equalizaion

 

 

پس طبق توضیحاتی که دادم مرحله آخری که گفتید اشتباهه .

بهترین منبع برای یادگیری به نظر من خوندن کتاب های  آمار هستش .

فصل سوم کتاب digital image processing gonzalez  هم در این مورد توضیحات کاملی داده .

پاسخ داده شده فروردین 4, 1393 بوسیله ی BlueBlade (امتیاز 15,315)   15 18 89
ویرایش شده بهمن 1, 1393 بوسیله ی haniye sarbazi
مرسی
در تابع نرمالایز x و x min و xmax چی هست؟
پاسخ رو ویرایش کردم .
در لینک زیر
http://en.wikipedia.org/wiki/Histogram_equalization
cdf, scaled در جدول چیست و چه طوری محاسبه شده و به چه دردی میخوره؟
scale مقادیر CDF بعد از normalize هستن که در مرحله ۳ حساب می کنیم . ( h(v
با به عبارتی ستون scale رنگ جدید پیکسل ها بعد از تعدیل هیستوگرامند .
+3 امتیاز

برای equalize کردن Histogram عکس رنگی بوسیله opencv

اول عکس رو به فضای رنگی YCrCb میبریم

بعد بر روی کانال مربوط به شدت نور بوسیله تابع equalizeHist عملیات مربوطه رو انجام میدیم

کد :

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace cv;

int main( )
{
    const char* original_window="Source";
    const char* equalized_window="Equalized image";

    Mat image = imread("F:\\image1.jpg");
    Mat equalized_image;
    std::vector<Mat> channels;

    cvtColor(image, equalized_image, CV_BGR2YCrCb); 

    split(equalized_image,channels);
    equalizeHist(channels[0], channels[0]);

    merge(channels,equalized_image); 
    cvtColor(equalized_image, equalized_image, CV_YCrCb2BGR);

    namedWindow(original_window,WINDOW_NORMAL);
    namedWindow(equalized_window,WINDOW_NORMAL);

    imshow(original_window,image);
    imshow(equalized_window,equalized_image);

    waitKey(0);
}

 

پاسخ داده شده فروردین 5, 1393 بوسیله ی BlueBlade (امتیاز 15,315)   15 18 89
میشه کدهارو خط به خط توضیح بدین
+3 امتیاز

این هم کدش به c++ که به راحتی قابل تبدیل به c# هستش.

#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using std::cout;
using std::cin;
using std::endl;

using namespace cv;

void imhist(Mat image, int histogram[])
{

    // initialize all intensity values to 0
    for(int i = 0; i < 256; i++)
    {
        histogram[i] = 0;
    }

    // calculate the no of pixels for each intensity values
    for(int y = 0; y < image.rows; y++)
        for(int x = 0; x < image.cols; x++)
            histogram[(int)image.at<uchar>(y,x)]++;

}

void cumhist(int histogram[], int cumhistogram[])
{
    cumhistogram[0] = histogram[0];

    for(int i = 1; i < 256; i++)
    {
        cumhistogram[i] = histogram[i] + cumhistogram[i-1];
    }
}

void histDisplay(int histogram[], const char* name)
{
    int hist[256];
    for(int i = 0; i < 256; i++)
    {
        hist[i]=histogram[i];
    }
    // draw the histograms
    int hist_w = 512; int hist_h = 400;
    int bin_w = cvRound((double) hist_w/256);

    Mat histImage(hist_h, hist_w, CV_8UC1, Scalar(255, 255, 255));

    // find the maximum intensity element from histogram
    int max = hist[0];
    for(int i = 1; i < 256; i++){
        if(max < hist[i]){
            max = hist[i];
        }
    }

    // normalize the histogram between 0 and histImage.rows

    for(int i = 0; i < 256; i++){
        hist[i] = ((double)hist[i]/max)*histImage.rows;
    }


    // draw the intensity line for histogram
    for(int i = 0; i < 256; i++)
    {
        line(histImage, Point(bin_w*(i), hist_h),
                              Point(bin_w*(i), hist_h - hist[i]),
             Scalar(0,0,0), 1, 8, 0);
    }

    // display histogram
    namedWindow(name, CV_WINDOW_AUTOSIZE);
    imshow(name, histImage);
}



int main()
{
    // Load the image
    Mat image = imread("scene.jpg", CV_LOAD_IMAGE_GRAYSCALE);

    // Generate the histogram
    int histogram[256];
    imhist(image, histogram);

    // Caluculate the size of image
    int size = image.rows * image.cols;
    float alpha = 255.0/size;

    // Calculate the probability of each intensity
    float PrRk[256];
    for(int i = 0; i < 256; i++)
    {
        PrRk[i] = (double)histogram[i] / size;
    }

    // Generate cumulative frequency histogram
    int cumhistogram[256];
    cumhist(histogram,cumhistogram );

    // Scale the histogram
    int Sk[256];
    for(int i = 0; i < 256; i++)
    {
        Sk[i] = cvRound((double)cumhistogram[i] * alpha);
    }


    // Generate the equlized histogram
    float PsSk[256];
    for(int i = 0; i < 256; i++)
    {
        PsSk[i] = 0;
    }

    for(int i = 0; i < 256; i++)
    {
        PsSk[Sk[i]] += PrRk[i];
    }

    int final[256];
    for(int i = 0; i < 256; i++)
        final[i] = cvRound(PsSk[i]*255);


    // Generate the equlized image
    Mat new_image = image.clone();

    for(int y = 0; y < image.rows; y++)
        for(int x = 0; x < image.cols; x++)
            new_image.at<uchar>(y,x) = saturate_cast<uchar>(Sk[image.at<uchar>(y,x)]);

   // Display the original Image
    namedWindow("Original Image");
    imshow("Original Image", image);

    // Display the original Histogram
    histDisplay(histogram, "Original Histogram");

    // Display equilized image
    namedWindow("Equilized Image");
    imshow("Equilized Image",new_image);

    // Display the equilzed histogram
    histDisplay(final, "Equilized Histogram");

    waitKey();
    return 0;
}
 

 

پاسخ داده شده فروردین 8, 1393 بوسیله ی مصطفی ساتکی (امتیاز 21,998)   24 34 75
درسته ولی چرا cdf رو در m*n ضرب میکنیم؟
نیازی به ضرب نداره برای سادگی محاسبات صورت و مخرج کسر ضرب کردن که مستقیم فراوانی گذاشته بشه.
در اصل روابط این 3 تا فرمول هستن :
http://latex.codecogs.com/gif.latex?\bg_black%20\fn_cm%20\large%20\frac{cdf%28v%29-cdf%28min%29}{1-cdf%28min%29}%20%2C%20%2C%20cdf%28v%29%3D\sum_{i}^{v}p%28i%29%20%2C%2C%20p%28i%29%3D\frac{number%20of%20pixel%28i%29}{total%20number%20of%20pixels%28or%20M*N%29}
پس در اصل همون فراوانی تحمعی ها رو در بازه 0 تا 255 نرمالیزه میکنیم.
اره مخرج 1 باشه حله مشکل این بود که تو مخرج m*n نوشتن
نه باید همون cdf ها  نرمالایز بشن .
من اون پست اولمو ویرایش کردم فکر کنم الان قابل فهم تره .
...