如何保存没有任何压缩的16位图像(PNG或TIFF)?语法是什么?
如何保存没有任何压缩的16位图像(PNG或TIFF)?语法是什么?
经过2年的发展,OpenCV现在可以保存带有压缩(LZW)的16位TIFF文件(2.4.x版本)。但是,在函数
bool imwrite(const string& filename, InputArray img, const vector<int>& params=vector<int>() )
中,它还支持一个未公开的参数TIFFTAG_COMPRESSION。
例如,它可以被设置为COMPRESSION_LZMA(并且正常工作)。
您可以将此参数的值设置为COMPRESSION_NONE(同时必须将TIFFTAG_ROWSPERSTRIP参数设置为图像高度)。
但是,在这种情况下(试图将TIFFTAG_COMPRESSION设置为COMPRESSION_NONE),即使在2.4.9版本中,OpenCV仍会生成错误的TIFF文件。
查看OpenCV源代码后,我找到了两种克服此限制的方法:
重新编译OpenCV并更改"opencv/modules/imgcodecs/src/grfmt_tiff.cpp"文件 - 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位上完美地编译)。
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);
至少从2.1版开始(未使用旧版本),cvSaveImage可以轻松保存单通道16位深度图像。我通常使用.png格式。
这将为您提供带有“somedata”的16位图像:
IplImage* image = cvCreateImage(cvSize(100,100),16,1);
memset(image->imageData,someData,image->width*image->height*2);
cvSaveImage("image.png",image);
我的经验是OpenCV将图像保存为16位(没有尝试过3个通道)。 pgm格式绝对可行,它是真正的原始格式(没有运行长度压缩)。