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$
1
  • $\begingroup$ I don't understand where is the threshold in you implmentation $\endgroup$
    – Gilad
    Jan 17, 2015 at 16:47

2 Answers 2

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.)

$\endgroup$
1
  • $\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, 2014 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++}
        }
    }
$\endgroup$
4
  • $\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, 2014 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, 2014 at 23:36
  • $\begingroup$ please check out this link. dsp.stackexchange.com/questions/15441/… $\endgroup$
    – CroCo
    Apr 5, 2014 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, 2014 at 2:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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