D. Sanz D. Sanz - 23 days ago 5
C++ Question

Bit planes of a 1-plane image in OpenCV only work for 1/3 of the image

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:

enter image description here

And here is it for the 7th bit:

enter image description here

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;
}
Comments