D. Sanz - 6 months ago 37

C++ Question

I'm trying to learn OpenCV by doing a few things on my own. In this particular case, I wanted to take the bit planes of a grayscale image. The code seems to have worked, but it only works well for the bit 7 and 6, not so much for the remaining 6, as it only shows a good result for about 1/3 of the image. I just haven't found what's wrong with it as of yet. I'd greatly appreciate some help on the matter, as I'm just doing my first codes with the libraries.

Here's what I get for the first bit:

And here is it for the 7th bit:

And here's my code:

`#include <opencv2\opencv.hpp>`

#include <math.h>

using namespace cv;

using namespace std;

int main( int argc, char** argv ) {

Mat m1 = imread("grayscalerose.jpg");

imshow("Original",m1);

int cols, rows, x, y;

cols = m1.cols;

rows = m1.rows;

printf("%d %d \n",m1.rows,m1.cols);

Mat out1(rows, cols, CV_8UC1, Scalar(0));

out1 = (m1/128); //Here's where I divide by either 1,2,4,8,16,32,64, or 128 to get the corresponding bit planes

for (int y = 0; y < rows; y++){

for (int x = 0; x < cols; x++){

out1.at<uchar>(y,x) = (out1.at<uchar>(y,x) % 2);

} }

out1 = out1*255;

imshow("out1",out1);

waitKey(0);

destroyWindow( "out1" );

}

Thanks in advance. I hope my explanation wasn't too messy.

Answer

When you divide `15`

(`0x00001111`

) by `2`

(`0x00000010`

) you get `7`

(`0x00000111`

), which is not what you expect. You can check if a bit is set like: `15 & 2`

, which produces 0 if second bit is not set, else a value greater then 0. The same applies for other values.

Try the following code. Note that:

- you need to load the image as grayscale (using
`IMREAD_GRAYSCALE`

in`imread`

) - you can directly put values either
`0`

or`255`

when you select the bit

Code:

```
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat m1 = imread("path_to_image", IMREAD_GRAYSCALE);
imshow("Original", m1);
int cols, rows, x, y;
cols = m1.cols;
rows = m1.rows;
printf("%d %d \n", m1.rows, m1.cols);
Mat out1(rows, cols, CV_8UC1, Scalar(0));
for (int y = 0; y < rows; y++){
for (int x = 0; x < cols; x++){
out1.at<uchar>(y, x) = (m1.at<uchar>(y, x) & uchar(64)) ? uchar(255) : uchar(0); //Here's where I AND by either 1,2,4,8,16,32,64, or 128 to get the corresponding bit planes
}
}
imshow("out1", out1);
waitKey(0);
destroyWindow("out1");
return 0;
}
```