我们使用opencv对TIFF格式图像进行处理,比如放大,缩小等基本操作,当我们需要存储所操作后的图像时就会存在问题。因为opencv中默认的函数imwrite()是将TIFF格式的图像存储为LZW压缩格式的图像,LZW压缩格式是一种无损的技术,但是在不同的应用场合我们可能需要未压缩的TIFF格式的图像。
Imwrite函数定义如下:boolimwrite(const string& filename, InputArray img, constvector<int>& params=vector<int>() )其第三个参数在opencv2.4.3中只有如下几个格式,并没有直接处理TIFF格式的。
enum cv::ImwriteFlags {
cv::IMWRITE_JPEG_QUALITY = 1,
cv::IMWRITE_JPEG_PROGRESSIVE = 2,
cv::IMWRITE_JPEG_OPTIMIZE = 3,
cv::IMWRITE_JPEG_RST_INTERVAL = 4,
cv::IMWRITE_JPEG_LUMA_QUALITY = 5,
cv::IMWRITE_JPEG_CHROMA_QUALITY = 6,
cv::IMWRITE_PNG_COMPRESSION = 16,
cv::IMWRITE_PNG_STRATEGY = 17,
cv::IMWRITE_PNG_BILEVEL = 18,
cv::IMWRITE_PXM_BINARY = 32,
cv::IMWRITE_WEBP_QUALITY = 64
}
所以我使用的opencv版本是2.4.3,该版本目前只支持简单存储TIFF格式图像,不能选择是否压缩,或者怎样压缩。所以,为了使用opencv处理TIFF格式图像,我们必须对其源码进行一定的修改,让其能够将TIFF格式的图像存储为未压缩格式。
找到opencv的源码中的grfmt_tiff.cpp文件,有如下部分代码:
int compression = COMPRESSION_LZW;
int predictor = PREDICTOR_HORIZONTAL;
int colorspace = channels > 1? PHOTOMETRIC_RGB : PHOTOMETRIC_MINISBLACK;
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;
}
将该部分代码修改为:
int compression = COMPRESSION_NONE;
int predictor = PREDICTOR_HORIZONTAL;
int colorspace = channels > 1? PHOTOMETRIC_RGB : PHOTOMETRIC_MINISBLACK;
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);
returnfalse;
}
并重新使用cmake编译opencv,然后使用其中的dll,就可以解决opencv只能将tiff存储为LZW压缩格式的问题。
使用cmake编译opencv,请自行百度,并且声明只是opencv2.4.3需要修改,至于之后现在最新的opencv是否有选择压缩的选项不清楚。还有一个弊端就是使用该方法之后,之后存储tiff格式的图像都不能存储为LZW格式的图像。
附上存储部分代码:
cv::Mat img1 = cv::imread("test.tif",-1);
cv::Matimg2;
resize(img1,img2,cv::Size(1320,1400),0,0,CV_INTER_LINEAR);
imwrite("test.tif",img2);