我正在使用的程序正在读取一些位图,并且需要32FC1图像。
我正在尝试制作这些图片
cv::Mat M1(255, 255, CV_32FC1, cv::Scalar(0,0,0));
cv::imwrite( "my_bitmap.bmp", M1 );
但是当我检查深度时 - 它总是CV_8U
如何创建文件以便它们包含正确的信息?
更新:如果我使用不同的文件扩展名,则没有区别 - 例如tif或png
我正在阅读它 - 使用已经实现的代码 - 使用cvLoadImage
。
我正在尝试创建现有代码(检查图像类型)可以使用的文件。
我无法转换现有代码中的文件。现有代码不会尝试读取随机图像类型并将其转换为所需类型,但会检查文件是否属于所需类型。
我发现了 - 谢谢你的答案 - cv :: imwrite只写整数类型的图像。
是否有另一种方式 - 使用OpenCV或其他方式 - 编写图像以便最终得到CV_32F类型?
再次更新 读取图像的代码......如果进入cv :: Mat:
cv::Mat x = cv::imread(x_files, CV_LOAD_IMAGE_ANYDEPTH|CV_LOAD_IMAGE_ANYCOLOR);
现有代码:
IplImage *I = cvLoadImage(x_files.c_str(), CV_LOAD_IMAGE_ANYDEPTH|CV_LOAD_IMAGE_ANYCOLOR);
答案 0 :(得分:3)
您的问题是位图在内部存储数据,因为整数不会浮动。如果在保存时出现问题是四舍五入错误,则需要使用不同的文件格式或在保存之前调高数据,然后在保存后退回。如果您只想转换在将文件读取到浮点数后得到的矩阵,则可以使用cv :: convertto
答案 1 :(得分:3)
cv::imwrite() .bmp编码器假设8位通道。
如果您只需要使用OpenCV编写.bmp文件,您可以将32FC1图像转换为8UC4,然后使用cv::imwrite()
进行编写,您将获得每像素32位的.bmp文件。
我猜你的程序读取文件会将32位像素解释为32FC1。
.bmp format没有明确的通道结构,只是每个像素的位数。因此,您应该能够在OpenCV中将32位像素写为4位8位通道,并在另一个程序中将其作为单通道32位像素读取 - 如果这样做,您需要了解读者的字节序假设。像以下一样的工作:
cv::Mat m1(rows, cols, CV_32FC1);
... // fill m1
cv::Mat m2(rows, cols, CV_8UC4, m1.data); // provide different view of m1 data
// depending on endianess of reader, you may need to swap byte order of m2 pixels
cv::imwrite("my_bitmap.bmp", m2);
您将无法正确读取您在OpenCV中创建的文件,因为OpenCV中的.bmp解码器假定该文件是1或3通道的8位数据(即它不能读取32位像素)。
修改强>
可能更好的选择是使用OpenEXR格式,OpenCV具有编解码器。我假设您只需要使用.exr扩展名保存文件。
答案 2 :(得分:0)
我在同一个问题上挣扎。最后,我决定编写一个可以编写和加载任意CV Mat的自定义函数会更容易。
bool writeRawImage(const cv::Mat& image, const std::string& filename)
{
ofstream file;
file.open (filename, ios::out|ios::binary);
if (!file.is_open())
return false;
file.write(reinterpret_cast<const char *>(&image.rows), sizeof(int));
file.write(reinterpret_cast<const char *>(&image.cols), sizeof(int));
const int depth = image.depth();
const int type = image.type();
const int channels = image.channels();
file.write(reinterpret_cast<const char *>(&depth), sizeof(depth));
file.write(reinterpret_cast<const char *>(&type), sizeof(type));
file.write(reinterpret_cast<const char *>(&channels), sizeof(channels));
int sizeInBytes = image.step[0] * image.rows;
file.write(reinterpret_cast<const char *>(&sizeInBytes), sizeof(int));
file.write(reinterpret_cast<const char *>(image.data), sizeInBytes);
file.close();
return true;
}
bool readRawImage(cv::Mat& image, const std::string& filename)
{
int rows, cols, data, depth, type, channels;
ifstream file (filename, ios::in|ios::binary);
if (!file.is_open())
return false;
try {
file.read(reinterpret_cast<char *>(&rows), sizeof(rows));
file.read(reinterpret_cast<char *>(&cols), sizeof(cols));
file.read(reinterpret_cast<char *>(&depth), sizeof(depth));
file.read(reinterpret_cast<char *>(&type), sizeof(type));
file.read(reinterpret_cast<char *>(&channels), sizeof(channels));
file.read(reinterpret_cast<char *>(&data), sizeof(data));
image = cv::Mat(rows, cols, type);
file.read(reinterpret_cast<char *>(image.data), data);
} catch (...) {
file.close();
return false;
}
file.close();
return true;
}