使用OpenCV写入16位未压缩的图像

时间:2012-08-22 12:34:33

标签: c++ image opencv

如何在不进行任何压缩的情况下保存16位图像(PNG或TIFF)?语法是什么?

5 个答案:

答案 0 :(得分:4)

2年后,OpenCV可以通过压缩(LZW)保存16位TIFF(2.4.x版本)。但它还支持函数

中未记录的参数TIFFTAG_COMPRESSION

bool imwrite(const string& filename, InputArray img, const vector<int>& params=vector<int>() )

例如,它可以设置为COMPRESSION_LZMA(并且正常工作)。

您可以使用COMPRESSION_NONE作为此参数的值(您还必须将TIFFTAG_ROWSPERSTRIP参数设置为图像高度)。

但OpenCV在这种情况下仍会生成错误的TIFF(尝试将TIFFTAG_COMPRESSION设置为COMPRESSION_NONE),即使在2.4.9版本中也是如此。

在查看OpenCV来源后,我发现了两种克服此限制的方法:

  1. 使用&#34; opencv / modules / imgcodecs / src / grfmt_tiff.cpp&#34;中的更改重新编译OpenCV; - 来自OpenCV的人添加了压缩参数,但忘记了如果我们不想要压缩,libtiff无法在TIFF句柄中设置预测器这一事实。你应该找到这个代码

    if ( !TIFFSetField(pTiffHandle, TIFFTAG_IMAGEWIDTH, width) || !TIFFSetField(pTiffHandle, TIFFTAG_IMAGELENGTH, height) || !TIFFSetField(pTiffHandle, TIFFTAG_BITSPERSAMPLE, bitsPerChannel) || !TIFFSetField(pTiffHandle, TIFFTAG_COMPRESSION, compression) || !TIFFSetField(pTiffHandle, TIFFTAG_PHOTOMETRIC, colorspace) || !TIFFSetField(pTiffHandle, TIFFTAG_SAMPLESPERPIXEL, channels) || !TIFFSetField(pTiffHandle, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG) || !TIFFSetField(pTiffHandle, TIFFTAG_ROWSPERSTRIP, rowsPerStrip) || !TIFFSetField(pTiffHandle, TIFFTAG_PREDICTOR, predictor) ) { TIFFClose(pTiffHandle); return false; }

    并将其更改为

    if ( !TIFFSetField(pTiffHandle, TIFFTAG_IMAGEWIDTH, width) || !TIFFSetField(pTiffHandle, TIFFTAG_IMAGELENGTH, height) || !TIFFSetField(pTiffHandle, TIFFTAG_BITSPERSAMPLE, bitsPerChannel) || !TIFFSetField(pTiffHandle, TIFFTAG_COMPRESSION, compression) || !TIFFSetField(pTiffHandle, TIFFTAG_PHOTOMETRIC, colorspace) || !TIFFSetField(pTiffHandle, TIFFTAG_SAMPLESPERPIXEL, channels) || !TIFFSetField(pTiffHandle, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG) || !TIFFSetField(pTiffHandle, TIFFTAG_ROWSPERSTRIP, rowsPerStrip) ) { TIFFClose(pTiffHandle); return false; } if (compression != COMPRESSION_NONE && !TIFFSetField(pTiffHandle, TIFFTAG_PREDICTOR, predictor) ) { TIFFClose(pTiffHandle); return false; }

    此OpenCV可以保存压缩和未压缩的TIFF(取决于imwrite的参数)。

  2. 另一种方法是直接在您的应用程序中使用libtiff来保存TIFF。当然,在这种情况下你需要实现写入功能。对于Windows,你应该编译libtiff,但它是一个相当简单的任务(libtiff包含许多编译器的makefile,并在MinGW和MSVC,32和64位完美编译)。

答案 1 :(得分:2)

根据OpenCV文档,cvSaveImage仅支持8bit单通道或BGR图像。 See 2.0 docs.

您应该使用libpng,libMagick ++或其他一些库来保存其他位深度和格式。

libpng文档包含how to write PNG images的教程。要指定每通道数据为16位的RGB,请使用bit_depth = 16和color_type = PNG_COLOR_TYPE_RGB。

为了让你的生活(可能)更容易一些,还有png++

编辑:OpenCV似乎支持在较新版本中编写16bpc图像。请参阅p.streef的答案。这是the link to the relevant documentation again.

答案 2 :(得分:2)

至少从2.1(未使用旧版本)cvSaveImage保存单个通道16b深度图像没有问题。我通常会使用.png。

这样可以获得带有“somedata”的16b图像:

IplImage* image = cvCreateImage(cvSize(100,100),16,1);
memset(image->imageData,someData,image->width*image->height*2);
cvSaveImage("image.png",image);

答案 3 :(得分:1)

如果其他任何人遇到这个avtomaton的解决方案似乎是通过拉取请求添加https://github.com/opencv/opencv/pull/3744

允许你做类似的事情(适用于3.2):

cv::Mat shorts(1024*cv::Mat::ones(100, 100, CV_16UC1));
vector<int> tags = {TIFFTAG_COMPRESSION, COMPRESSION_NONE};

bool success = cv::imwrite("uncompressed.tif", shorts, tags);

答案 4 :(得分:0)

我的经验是,OpenCV将图像保存为16位(未尝试使用3个通道)。 pgm格式绝对有效,它是一种真正的原始格式(没有运行长度压缩)。