如何在不进行任何压缩的情况下保存16位图像(PNG或TIFF)?语法是什么?
答案 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来源后,我发现了两种克服此限制的方法:
使用&#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
的参数)。
另一种方法是直接在您的应用程序中使用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格式绝对有效,它是一种真正的原始格式(没有运行长度压缩)。