how to plot histogram of image using visual studio

Discussion in 'C' started by metamofia, Oct 9, 2009.

  1. metamofia

    metamofia New Member

    Joined:
    Sep 28, 2009
    Messages:
    47
    Likes Received:
    0
    Trophy Points:
    0
    hi guys im on a project to come up with a histogram equalization but right now i need to display the histogram for now. so far everything i did was okay to me except that my histogram is not a proper one. here is my code below:

    Code:
     
    //**************************************************************************************//
    void CLEO_MedivisionView::OnUpdateToolsHistogram(CCmdUI *pCmdUI)
    {
    // TODO: Add your command update UI handler code here
    
    if (fileopen)
    {
    pCmdUI->Enable(true);
    }
    else
    {
    pCmdUI->Enable(false);
    }
    }
    void CLEO_MedivisionView::OnToolsHistogram()
    {
    // TODO: Add your command handler code here
    int x_tick, y_tick;
    int j;
    int a_loop, b_loop;
    int k, t, f, i;
    int x;
    int q;
    unsigned int intMFC;
    unsigned int intMFC1;
    unsigned int intMFC2;
    unsigned short array1[256];
    char c[10];
    char p[10];
    char l[10];
    CString MFCString;
    
    pDC = GetDC(); //OnDraw member function
    hdc = pDC->GetSafeHdc();
    CPen aPen, greenPen;
    aPen.CreatePen(PS_SOLID, 2, RGB(255, 225, 225));
    greenPen.CreatePen(PS_SOLID, 1, RGB(124, 252, 0));
    CPen* pOldPen = pDC->SelectObject(&aPen);
     
    pDC->MoveTo(600,400); //drawing of x-axis
    pDC->LineTo(920,400);
    pDC->MoveTo(920,400);
    pDC->LineTo(915,405);
    pDC->MoveTo(920,400);
    pDC->LineTo(915,395); //drawing of x-axis
    
    x_tick = 600; //declaring constants
    y_tick = 400;
    for(j=1; j<=10; j++) //control the loop so that it draws ticks every 30 pixels
    {
    pDC->MoveTo(x_tick+(j*30),y_tick-5); 
    pDC->LineTo(x_tick+(j*30),y_tick+5); 
    }
    pDC->MoveTo(600,400); //drawing of y-axis
    pDC->LineTo(600,80);
    pDC->MoveTo(600,80);
    pDC->LineTo(605,85);
    pDC->MoveTo(600,80);
    pDC->LineTo(595,85); //drawing of y-axis
    for(t=1; t<=10; t++) //control the loop so that it draws ticks every 30 pixels
    {
    pDC->MoveTo(x_tick-5,y_tick-(t*30)); 
    pDC->LineTo(x_tick+5,y_tick-(t*30));
    }
    intensity= "Intensity"; //labelling of x-axis
    SetBkColor(hdc, RGB(0, 0, 0));
    SetTextColor(hdc, RGB(255, 255 ,255 ));
    TextOut(hdc, 930, 390, LPCTSTR(intensity), 9);
    pixels = "Pixels"; //labelling of y-axis
    SetTextColor(hdc, RGB(255, 255 ,255 ));
    TextOut(hdc, 580, 55, LPCTSTR(pixels), 6); 
    numeric = "0"; //number zero (universal)
    SetTextColor(hdc, RGB(95, 158, 160));
    TextOut(hdc, 585, 400, LPCTSTR(numeric),1);
    intMFC = 0; //declaring constants
    a_loop = 595;
    for(k=1; k<=5; k++) //for every two ticks, draw legend of +52 each time it loops
    { 
    intMFC = intMFC+51;
    itoa(intMFC,c,10);
    CString MFCString;
    MFCString = c;
    if(intMFC<100) //if number is XX then just show 2 digits
    {
    test = c;
    SetTextColor(hdc, RGB(95, 158 ,160));
    TextOut(hdc, a_loop+(k*60), 405, LPCTSTR(test), 2);
    }
    else if(intMFC>=100) //if number is XXX then show 3 digits
    {
    test = c;
    SetTextColor(hdc, RGB(95, 158, 160));
    TextOut(hdc, a_loop+(k*60), 405, LPCTSTR(test), 3);
    }
    }
    intMFC1 = 0; //declaring of constants
    intMFC2 = 0;
    b_loop = 392;
    
    
    //'for' loop couting from 0 to 255 which simply zeros out each element in array1 to prepare the array to do the count of the bytes in the image
    for (i=0;i<256;i++) 
    {
    array1[i]=0;
    }
    //'for' loop to loop through the bytes of the image
    for (i=0; i<262144; i++)
    { 
    array1[image[i]]++;
    }
    for (i=0; i<65536; i++)
    {
    array1[image256[i]]++;
    }
    
    //find the array location containing most value
    int highest=0; 
    for (int i=0; i<256; i++) 
    {
    if (array1[i] > highest)
    highest = array1[i];
    }
    if (no_of_rows == 256 && no_of_cols == 256) // initiate if image its by 256*256
    {
    for(f=1; f<=5; f++) // for 5-ticks axis
    { 
    intMFC1 = (((highest+99)/100)*100)/5*f; // calculation
    itoa(intMFC1,p,10); 
    CString MFCString;
    MFCString = p;
    if(intMFC1<10000)
    {
    test1=p;
    SetTextColor(hdc, RGB(95, 158 ,160));
    TextOut(hdc, 540, b_loop-(f*60), LPCTSTR(test1), 4);
    } 
    else if(intMFC1>=10000)
    { 
    test1 = p;
    SetTextColor(hdc, RGB(95, 158 ,160));
    TextOut(hdc, 540, b_loop-(f*60), LPCTSTR(test1), 5);
    }
    }
    }
    else if (no_of_rows == 512 && no_of_cols == 512) // if image is 512*512 run this
    {
    for(q=1; q<=5; q++) // for 5-ticks axis 
    { 
    intMFC2 = (((highest+99)/100)*100)/5*q; // calculation
    itoa(intMFC2,l,10); 
    
    MFCString = l; 
    if(intMFC2<10000) 
    
    {
    test2 = l;
    SetTextColor(hdc, RGB(95, 158 ,160));
    TextOut(hdc, 540, b_loop-(q*60), LPCTSTR(test2), 4); 
    }
    else if(intMFC2>=10000) //if digit is more or equal to 100000, do this
    {
    test2 = l;
    SetTextColor(hdc, RGB(95, 158, 160));
    TextOut(hdc, 540, b_loop-(q*60), LPCTSTR(test2),5);
    }
    }
    }
    
    //green colour pen for histogram lines
    CPen* gOldPen = pDC->SelectObject(&greenPen);
    //starting of histogram drawing (intensity vs pixel value)
    pDC->MoveTo(600, 398);
    for (i=1; i<256; i++)
    
    { 
    pDC->MoveTo(600+i, 398);
    pDC->LineTo(600+i, (398-(array1[i]*398/highest)));
    }
    }
    
    when i run this program, the histogram was displayed in a distorted manner. i will post a screenshot attached to this post. so right now, as instructed by my supervisor, i need to display the histogram properly before i can do anything else. as you will see, the y-axis, or the pixel number axis is scaled to show only the total number of pixels of the intensity value(ie 0-255). for example array1[200]= 43456. so this intensity has the msot pixel value so my y-axis will be in range from 0-43500. its already scaled. so if possible pls help me on the plotting of the histogram. thanks alot.
     

    Attached Files:

    Last edited: Oct 9, 2009
  2. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    What should it look like?

    As previously suggested, if you output the values used in drawing the histogram to a file, can you see from the resulting numbers what is wrong?

    Looking at the image, it's compressed so I can't make it out clearly, but you do seem to have a large number of faint pixels and a smaller number of brighter ones, and the resulting histogram does seem to fit the image. Have you tried pasting a screen shot into an application that can do histograms to see what it makes of the image? For example Paint Shop Pro can do histograms, and the one it plots for the image looks very similar to the one you've already plotted.

    So are you sure it's wrong? If so can you describe exactly how it's wrong?
     
  3. metamofia

    metamofia New Member

    Joined:
    Sep 28, 2009
    Messages:
    47
    Likes Received:
    0
    Trophy Points:
    0
    Hi, well is it possible for u to zoom the thumbnail i attached earlier? well seemingly as you can roughly see: my x-axis starts from 0-255 and its 320 pixels long. so by right my histogram should stretch all the way to the ticker 255 but currently it just occupy a small portion for whatever reasons. and yes, i did check the values in array1[] and seems reasonable cause, ie array1[0] has 45000+ pixels since most of the image is black. and the gray values are equally distributed. so the problem now lies on the plotting of histogram i think. and if you can roughly see my y-axis, its program so that the peak of it just show the most NUMBER OF PIXELS FOR A PARTICULAR INTENSITY. for example since my black has 45000 pixels, then the y-axis range is from 0-45000. so also in this case my histogram should stretch to the y axis. but unfortunately its not. any ideas?

    PS: i dont have the application with me and the only few things available in my project PC is Visual Studio C++. Not even Paint software. Thanks for the help.
     
    Last edited: Oct 12, 2009
  4. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    Have another look at the for loop and see if you can see any reason it might not plot the array1[0] line (hint: there is a reason, so you just need to look at it until you see it, and NO I'm not going to give it away so don't ask -- finding bugs is what programming is all about. I'm already giving you a massive hint just by telling you where to look. If you don't want to learn how to find bugs then you're in the wrong job, probably 90% of programming is bug-fixing.)

    Attached is what Paint Shop Pro thinks your histogram should look like. It's very similar to what you've already got. Why do you think your histogram should look any different? If what you want is for the curve to be scaled over the width, then you will need to perform similar scaling for what you did with the y-axis, i.e. work out the range of data you want to display then scale that to fit the available screen.
     

    Attached Files:

  5. metamofia

    metamofia New Member

    Joined:
    Sep 28, 2009
    Messages:
    47
    Likes Received:
    0
    Trophy Points:
    0
    Okay thanks i think i know where i went bonkers. my condition was set to i=1 onwards. i have ammended it and now the array1[0] line is there and its shot to infinity. i will attached the thumbnail below.

    okay what im trying to say earlier was: my y-axis is coded in a way that the Max value of the axis = the total number of pixel that has the most repetition of the same intensity value. in referrence to the thumbnail, the the total number of pixel that has the most repetition is the black intensity and its 43542.

    so i came up with this algorithm:
    Code:
     
    int highest=0; 
    for (int i=0; i<256; i++) 
    {
    if (array1[i] > highest)
    highest = array1[i];
    
    }

    intMFC2 = (((highest+99)/100)*100)/5*q
    this equation is use to round up to the nearest 100 which in this case will be 43600 and its correct. so as ur advised, the histogram need not to be stretched along the x-axis but there is a problem along the y-axis. any hints or help? thanks alot.
     

    Attached Files:

    Last edited: Oct 12, 2009
  6. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    What point on the screen do you want the higher end of the array1[0] line to end at?
    What is the value in array1[0]?
    Is it equal to highest?
    What will be the result of the calculation 398-(array1[0]*398/highest)?
     
  7. metamofia

    metamofia New Member

    Joined:
    Sep 28, 2009
    Messages:
    47
    Likes Received:
    0
    Trophy Points:
    0
    What point as in the EXACT (x,y) pixel values on the screen?

    For the image in the thumbnail, the value of array1[0] is 43542 hence, during the plotting of the legend on the marker on y axis, the max value is rounded up to 43600 so i want the line to end just slightly below the 43600 marker just to show the difference.

    As for this line of equation >> 398-(array1[0]*398/highest),
    im not sure the numeric result and i was just playing around with the values within the bracket since the '398-' is used for normalization on the histogram. frim what i know so far (not much actually), i need to do a scaling or proportionating. but im not too sure how to kickstart it.
     
  8. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    > What point as in the EXACT (x,y) pixel values on the screen?

    Yes. It seems to me that you need to know this to work out an equation to return this result from the variables and constants you have.

    > im not sure the numeric result

    OK, so as previously advised, write this stuff out to a file. Then you know for certain what numbers it's using. It would also help you to write out the contents of array[] to the file, I think.

    None of the questions I asked are without a point. So for your own benefit you should try to answer them. If you don't then it also makes me wonder what the point of replying further to this thread is.
     
  9. metamofia

    metamofia New Member

    Joined:
    Sep 28, 2009
    Messages:
    47
    Likes Received:
    0
    Trophy Points:
    0
    Okay got it. Well it has to be (600,100) = the rounded up value which is 43600
    So for this case my ACTAUAL highest is 43542, so by simple math it would be (600,101).

    And yes, i do have the contents of array1[] for example array1[4]=values array1[222]=values1. is this what u meant?

    Yeah i know i might be very slow in this. My supervisor isnt around so i got alot of confusion and doubts.
     
  10. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    It doesn't really matter that your supervisor isn't around; you're writing the program, not him, so it's up to you to solve these problems. You can do it; based on the code you've written so far there is nothing here you can't do. All you need is a cool rational head and to sit down and think this stuff through logically. There is nothing here you can't solve with simple algebra.

    So the vertical space for the line is from 100 to 398, so you want an equation that will give 398 when you feed in 0, and 100 when you feed in 43600. Put another way, you want to find f(), where f(0)=398 and f(43600)=100.

    You could simplify this by removing the inversion, so if necessary, start by finding an equation that will give you 398 when you feed in 100 and 100 when you feed in 43600. Then you just need to subtract that from something.

    The array values will help you picture in your mind what the resulting histogram should look like. Also you could try outputting the scaled values as well and maybe the coordinates of the lines, so the first line of the file might read something like:
    array[0]=43542; scaled=297; line=(600,398)-(600,101)
    Basically you want anything in this output file that will help you (a) FIND the problem and (b) QUANTIFY the problem, and if necessary (c) post the values here with an explanation of where you're stuck so that I can give you a hint, or just the answer if it's clear you've got a mental block. But the more answers I give you the more you'll come to depend on that, so you need to start solving these yourself, and that will give you the insight and confidence that you need to get onto the next problem. So for example I gave you the expression "398-(array1*398/highest)", but clearly this is a black box to you; you haven't got the faintest idea what it's doing, otherwise you'd be able to figure out how to change it to get the result you want. Maybe the problem is that you've convinced yourself that this is much more difficult than it is and are looking past all the easy answers on the grounds that they're not complicated enough. It's very common for beginners to do this, and in reality a lot of programming is really very simple.

    And I bet you're wondering where I got 297 from. Hint: what do you get if you subtract it from 398?

    The key to debugging is just to ask the following questions, in order:
    (1) What do I expect the program to do, in quantifiable terms?
    (2) Is the program doing what I expect?
    (3) If not, what exactly is it doing wrong, in quantifiable terms?
    (4) Why is it doing what it is doing and not what I expect?
    (5) How can it be modified to do what I expect instead of what it is doing?
     
  11. metamofia

    metamofia New Member

    Joined:
    Sep 28, 2009
    Messages:
    47
    Likes Received:
    0
    Trophy Points:
    0
    Okay i very much understand. But seriously i havent got any idea on how to kickstart it.
    All i know is: - i need to scale down the histogram.


    Hmm, thanks for ur explaination but i figured out something. The result is my histogram seems to be in scale AND it is consistent to any image (but sizes 512*512 and 256*256). I got what u mean but the thing is i dont really know an exactl algorith to start with. I looked over the internet and surprisingly there isnt anyone who is doing/did what i'm doing. Can u pls help me to check if what im doing is correct? i will post the thumbnails here. One will be the usual MRI scan image and the other is a random tile of only black and white colours.

    Here is what i did:

    pDC->LineTo(601+i, (398-(0.742*array1*398/highest))-1);

    the bold is a constant or some say; the scale factor and the one in italic is to show the normalized value.
     

    Attached Files:

    Last edited: Oct 14, 2009
  12. xpi0t0s

    xpi0t0s Mentor

    Joined:
    Aug 6, 2004
    Messages:
    3,009
    Likes Received:
    203
    Trophy Points:
    63
    Occupation:
    Senior Support Engineer
    Location:
    England
    I can't check if what you're doing is correct because, and read this carefully, repeatedly until you get it if necessary:

    >>> I don't know what your definition of CORRECT is <<<

    Without that information I really cannot help you. What do you think they SHOULD look like? You seem convinced that they are wrong, but despite me asking 1000000 times you STILL won't quantify (i.e. describe in specific/measurable terms) exactly what is wrong with the histograms. All you keep doing is posting stuff, declaring it to be wrong, asking me to help you fix it, but not telling me what is wrong!

    FWIW they both look correct to me. I haven't counted the pixels, obviously, but there is much less black than white in the tiles and the black line on the histogram is shorter than the white. And as I've already shown your other histogram looks exactly the same as the histogram drawn up by PSP.
     
  13. metamofia

    metamofia New Member

    Joined:
    Sep 28, 2009
    Messages:
    47
    Likes Received:
    0
    Trophy Points:
    0
    Alright thanks. I think i will just start of with the histogram equalization section right now. Thanks for ur help once again :)
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice