【问题标题】:Why does imwrite on BMP image gets stuck / does not return?为什么 imwrite on BMP 图像卡住/不返回?
【发布时间】:2020-02-13 10:01:52
【问题描述】:

我正在从磁盘读取位图文件,并在经过一些操作后将副本写回磁盘,同时也写入原始文件的副本。位图相对较小,分辨率为31 x 31 像素。

我看到的是,当我的分辨率为30 x 30 像素时,cv::imwrite 正确地写出文件,但是如果我选择31 x 31 像素的分辨率,那么cv:imwrite 就会卡住并且不会返回。这发生在相同的目录上。

<...>
image = cv::imread(imageName, IMREAD_GRAYSCALE); // Read the file
if( image.empty() )                      // Check for invalid input
{
    cout <<  "Could not open or find the image" << std::endl ;
    return -1;
}
Mat image_flip (width,height,CV_8U);

int8_t pixel_8b;
for (int i=0; i< width; i++){
    for (int j=0; j < height; j++){
        pixel_8b= image.at<int8_t>(i,j);
        image_flip.at<int8_t>(width-i,j) = pixel_8b;
    }
}
cout << "Writing files" << endl;
result=cv::imwrite("./output_flip.bmp", image_flip);

cout << result << endl;
return 0;

在好的情况下,我将文件output_flip.bmp 写入磁盘并显示result。在被卡住的糟糕情况下,我看到的最后一件事是“写入文件”,然后就什么也没有了。只需调整输入图像的大小,我就可以在好情况和坏情况之间来回切换。

有什么办法可以解决这个问题吗?

【问题讨论】:

  • OpenCV 很难处理分辨率不是 8 倍数的图像。但 30 不是 :D 但至少是偶数。我认为 31 对于 OpenCV 来说可能太小而且太具体了。我遇到过类似的问题,我使用 IPLimages 和他们一起延迟并硬设置他们的image.aligmnet
  • resultwidthheight 是如何分配的。请分享整个代码!!!
  • 你一定要用BMP格式的文件吗?它们确实是一个糟糕的选择,因为 Microsoft 从未发布过明确的、明确的规范,而且它们不节省空间并且不支持 16 位数据。

标签: c++ opencv bitmap


【解决方案1】:

正如 cmets 中已经讨论的那样,您没有提供 minimal, reproducible example (MRE)。因此,我从您的代码中导出了以下 MRE,因为我想指出几件事(并且想知道您的代码究竟是如何工作的):

#include <opencv.hpp>

int main()
{
    cv::Mat image = cv::imread("path/to/your/image.png", cv::IMREAD_GRAYSCALE);

    // cv::resize(image, image, cv::Size(30, 30));

    cv::Mat image_flip(image.size().height, image.size().width, CV_8U);

    for (int i = 0; i < image.size().width; i++) 
    {
        for (int j = 0; j < image.size().height; j++) 
        {
            const uint8_t pixel_8b = image.at<uint8_t>(j, i);
            image_flip.at<uint8_t>(j, image.size().width - 1 - i) = pixel_8b;
        }
    }

    std::cout << "Writing files" << std::endl;
    const bool result = cv::imwrite("./output_flip.bmp", image_flip);

    std::cout << result << std::endl;

    return 0;
}
  • 对于单通道、8 位图像 (CV_8U),在访问单个像素时使用 uint8_t
  • 使用.at 时,请注意语法为.at(y, x)。对于方形图像,它可能是相等的,但一般来说,它是错误的常见来源。
  • 如果width = image.size().width,则i = 0 访问.at(j, width-i) 必须失败,因为image 的最后一个索引是width - 1

纠正这些问题后,我可以毫无问题地运行您的代码以获取更大的图像,以及将图像大小调整为 30 x 3031 x 31。所以,请看一下,如果您可以通过相应地修改代码来解决您的问题。

(我知道,我的回答中根本没有解决问题中所述的实际问题(挂起imwrite),但正如我所说,我什至无法在第一个运行提供的代码地点...)

希望有帮助!

【讨论】:

  • 你好@HansHirse,我又觉得自己很年轻,也就是没有经验。 8o(监督丢失的“-1”实际上是这里的主要原因。也非常感谢您指出(y,x)与(x,y)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多