1
$\begingroup$

I have a problem with Otsu's method. I would like to implement histogram to compute how many ones' and zeros'. For Otsu's method, I have a code from a book and it is running without problem. This is the picture

here.

I've implemented a code to compute the histogram. This is the output of my code.

------------------
    0 : 14332
    1 : 2102
    2 : 1387
    3 : 745
    4 : 221
    5 : 117
    6 : 27
    7 : 9
  248 : 6
  249 : 12
  250 : 48
  251 : 162
  252 : 396
  253 : 830
  254 : 1377
  255 : 28554
------------------

Here's my code:

I = imread('images.jpg');
level = graythresh(I);
BW = im2bw(I, level);
imshow(BW)
imwrite(BW, 'img.jpg');

This is my C++ code.

#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv\cv.h>
#include <map>
#include <iomanip>

std::map<int, int> computeHistogram(const cv::Mat& image)
{
    std::map<int, int> histogram;

    for ( int row = 0; row < image.rows; ++row)
    {
        for ( int col = 0; col < image.cols; ++col)
        {
          ++histogram[(int)image.at<uchar>(row, col)];

        }
    }

    return histogram;
}

void printHistogram(const std::map<int, int>& histogram)
{
    std::map<int, int>::const_iterator histogram_iter;
    std::cout << "\n------------------\n";
    for( histogram_iter = histogram.begin(); histogram_iter != histogram.end(); ++histogram_iter)
    {
      std::cout << std::setw(5) << histogram_iter->first <<  " : " << histogram_iter->second << "\n";
    }
    std::cout << "------------------\n";
}

int main(int argc, char **argv)
{
    cv::Mat img = cv::imread("img.jpg", CV_BGR2GRAY);
    printHistogram(computeHistogram(img));
    return 0;
}

Why this is the result? What I'm expecting is how many 255 and 0 (black and white only). Moreover, if I run another picture, I get another results with the range 0-255.

$\endgroup$
  • $\begingroup$ I don't understand where is the threshold in you implmentation $\endgroup$ – Gilad Jan 17 '15 at 16:47
4
$\begingroup$

jpg is a compressed storage format and no matter how binary your image is, you will almost always end up with gray values in the resulting image (due to compression). Please save it as png and try again.

(Also note that you still have 0s and 255s as the dominant bins, because jpg generally degrades around the edges, which constitute a small portion in the image.)

| improve this answer | |
$\endgroup$
  • $\begingroup$ you are absolutely right. I've changed it to .png and this is what I got. ` ------------------ 0 : 16886 255 : 33439 ------------------` $\endgroup$ – CroCo Apr 5 '14 at 20:45
0
$\begingroup$

There's obviously more than just 0 and 255 valued pixels. I'd suggest implementing a thresholding preprocessor. This way you can convert anything close to white to completely white, and anything close to black to completely black. Not sure what language you're using but here's an example of what I mean.

for (i = 0; i < columnsSize, i++){
    for (j = 0; j < rowsSize, j++){
       if (image(i, j) < 100)   image(i,j) = 0;
       else  image(i,j) = 255;
    }
}

Better yet, thresholding + counter

int black = 0;
int white = 0;
    for (i = 0; i < columnsSize, i++){
        for (j = 0; j < rowsSize, j++){
           if (image(i, j) < 100)   {image(i,j) = 0; black++}
           else  {image(i,j) = 255; white++}
        }
    }
| improve this answer | |
$\endgroup$
  • $\begingroup$ I couldn't tag C++ because I don't have enough reputation. I'm using C++ and the part of the code for this matter as following /* Threshold */ pp = x->data[0]; for (i=0; i<n; i++) if (*pp < t) *pp++ = 0; else *pp++ = 255; where t is threshold. This is why I asked I don't know why this happens. $\endgroup$ – CroCo Apr 2 '14 at 22:19
  • $\begingroup$ Sounds like a syntax error rather than technique. For better assistance showing this code would get you better help. $\endgroup$ – Iancovici Apr 2 '14 at 23:36
  • $\begingroup$ please check out this link. dsp.stackexchange.com/questions/15441/… $\endgroup$ – CroCo Apr 5 '14 at 2:48
  • $\begingroup$ @CroCo the problem is that you're not thresholding like I was telling you in this answer. Re read what I posted, I'm implying you want to binaries this image. Yo do this by reading every pixel and if it's under a threshold, set it to 0, if it's above threshold then set it to 255. $\endgroup$ – Iancovici Apr 5 '14 at 2:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.