C++ OpenCV中单平面图像的位平面仅适用于图像的1/3

C++ OpenCV中单平面图像的位平面仅适用于图像的1/3,c++,opencv,image-processing,C++,Opencv,Image Processing,我试图通过自己做一些事情来学习OpenCV。在这个特殊的例子中,我想要获取灰度图像的位平面。代码似乎已经运行,但它只对第7位和第6位运行良好,而对其余的6位运行不太好,因为它只对大约1/3的图像显示了良好的结果。到目前为止,我还没有发现它有什么问题。我非常感谢在这件事上的一些帮助,因为我正在用这些库编写我的第一个代码 以下是我第一部分的收获: 这是第7位的代码: 这是我的代码: #include <opencv2\opencv.hpp> #include <math.h&g

我试图通过自己做一些事情来学习OpenCV。在这个特殊的例子中,我想要获取灰度图像的位平面。代码似乎已经运行,但它只对第7位和第6位运行良好,而对其余的6位运行不太好,因为它只对大约1/3的图像显示了良好的结果。到目前为止,我还没有发现它有什么问题。我非常感谢在这件事上的一些帮助,因为我正在用这些库编写我的第一个代码

以下是我第一部分的收获:

这是第7位的代码:

这是我的代码:

#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" );

}
#包括
#包括
使用名称空间cv;
使用名称空间std;
int main(int argc,字符**argv){
Mat m1=imread(“grayscalerose.jpg”);
imshow(“原件”,m1);
整数列,行,x,y;
cols=m1.cols;
行=m1.5行;
printf(“%d%d\n”,m1.rows,m1.cols);
Mat out1(行、列、CV_8UC1、标量(0));
out1=(m1/128);//这里我除以1、2、4、8、16、32、64或128得到相应的位平面
对于(int y=0;y

提前谢谢。我希望我的解释不要太混乱。

默认情况下,
cv::imread
将图像读取为BGR矩阵,但您将矩阵作为一个通道进行索引


只需将读取行更改为
matm1=imread(“grayscalerose.jpg”,0)15
0x00001111
)除以
2
0x00000010
)时,您会得到
7
0x0000111
),这不是您所期望的。您可以检查一个位是否设置为:
15&2
,如果未设置第二个位,则生成0,否则生成大于0的值。这同样适用于其他值

请尝试以下代码。请注意:

  • 您需要以灰度方式加载图像(使用
    IMREAD
    中的
    IMREAD\u grayscale
  • 选择位时,可以直接输入值
    0
    255
代码:

#包括
使用名称空间cv;
int main()
{
Mat m1=imread(“路径到图像”,imread\u灰度);
imshow(“原件”,m1);
整数列,行,x,y;
cols=m1.cols;
行=m1.5行;
printf(“%d%d\n”,m1.rows,m1.cols);
Mat out1(行、列、CV_8UC1、标量(0));
对于(int y=0;y
首先,让我们以仅灰度的形式读取图像。(如所述)

然后,让我们准备一个掩码图像,其中只设置最低有效位,即所有值都是1

算法简单。让我们避免每像素操作(两个嵌套for循环),并尝试利用OpenCV提供的优化操作

对于每个位(0..7):

  • 屏蔽工作图像中的最低阶位
  • 将遮罩图像缩放255以使其成为黑色/白色
  • 存储输出
  • 将工作图像中的值除以2——即将所有位向右移动1个位置
代码:

#包括
#包括
int main(int argc,字符**argv)
{
cv::Mat input_img(cv::imread(“peppers.png”,0));
int32_t行(input_img.rows),cols(input_img.cols);
cv::Mat bit_掩码(cv::Mat::ones(行、列、cv_8UC1));
cv::Mat work_img(input_img.clone());
字符串文件名(“peppers\u bit0.png”);
对于(uint32_t i(0);i<8;++i){
cv::垫出;
cv::按位和(工作模式、位掩码、输出);
out*=255;
cv::imwrite(文件名,out);
工时=工时/2;
文件名[11]+=1;
}
}
我们可以使用一个单独的开发工具开发更短(可能更快)的版本


我们可以使用表达式
(1
Mat Out(In/(1感谢您与我分享如此详细的答案。我必须承认,关于矩阵表达式和uint32_t的使用的部分我不是很清楚。如果我可以问一下,它们到底是如何工作的?@D.Sanz
uint32_t
只是一个32位宽的无符号整数的a。我更喜欢显式的,所以很明显我使用的是什么类型,无论what platform我在.@D.Sanz上编译了关于矩阵表达式的代码:OpenCV的编写方式,在数组上返回“矩阵表达式”(一种特殊类型)将单个C++表达式中的这些操作组合在一起,编译器就可以在代码的特定代码段中生成优化的代码。..SANZ,利用OpenCV提供执行每个元素分割、乘法和按位的运算符重载。此外,我使用表达式<代码>(1)为什么我的评论只出现在开头的一小部分?完整评论:@Dan Mašek:but,Mat Out(在/(1)中)
#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;
}
#include <opencv2\opencv.hpp>
#include <cstdint>

int main(int argc, char** argv)
{
    cv::Mat input_img(cv::imread("peppers.png", 0));

    int32_t rows(input_img.rows), cols(input_img.cols);

    cv::Mat bit_mask(cv::Mat::ones(rows, cols, CV_8UC1));

    cv::Mat work_img(input_img.clone());
    std::string file_name("peppers_bit0.png");
    for (uint32_t i(0); i < 8; ++i) {
        cv::Mat out;
        cv::bitwise_and(work_img, bit_mask, out);

        out *= 255;
        cv::imwrite(file_name, out);

        work_img = work_img / 2;
        file_name[11] += 1;
    }
}
#include <opencv2\opencv.hpp>
#include <cstdint>

int main(int argc, char** argv)
{
    cv::Mat input_img(cv::imread("peppers.png", 0));

    std::string file_name("peppers_bit0.png");
    for (uint32_t i(0); i < 8; ++i) {
        cv::Mat out(((input_img / (1<<i)) & 1) * 255);
        cv::imwrite(file_name, out);

        file_name[11] += 1;
    }
}