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

C++ 使用OpenCV写入16位未压缩图像,c++,image,opencv,C++,Image,Opencv,如何在不进行任何压缩的情况下保存16位图像(PNG或TIFF)?语法是什么?根据OpenCV文档,cvSaveImage仅支持8位单通道或BGR图像 您应该使用libpng、libMagick++或其他库以其他位深度和格式保存 libpng文档包含一个关于的教程。要指定每个通道16位数据的RGB,请使用位深度=16和颜色类型=PNG\U颜色类型\U RGB 为了让你的生活(可能)轻松一点,还有 编辑:OpenCV似乎支持在较新版本中编写16bpc的图像。见p.streef的答案。我的经验是,Op

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

根据OpenCV文档,cvSaveImage仅支持8位单通道或BGR图像

您应该使用libpng、libMagick++或其他库以其他位深度和格式保存

libpng文档包含一个关于的教程。要指定每个通道16位数据的RGB,请使用位深度=16和颜色类型=PNG\U颜色类型\U RGB

为了让你的生活(可能)轻松一点,还有


编辑:OpenCV似乎支持在较新版本中编写16bpc的图像。见p.streef的答案。我的经验是,OpenCV将图像保存为16位(没有尝试使用3个通道)。 pgm格式绝对有效,它是一种真正的原始格式(无运行长度压缩)。

至少从2.1版(未使用旧版本)开始,cvSaveImage可以毫无问题地保存单通道16b深度图像。我通常用.png来做这个

这将获得一个带有“somedata”的16b图像:


两年后,OpenCV可以通过压缩(LZW)保存16位TIFF(2.4.x版本)。但它也支持函数中未记录的参数TIFFTAG_压缩

bool imwrite(常量字符串和文件名、输入数组img、常量向量和参数=vector())

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

您可以使用COMPRESSION_NONE作为此参数的值(还必须将TIFFTAG_ROWSPERSTRIP参数设置为image height)

但即使在2.4.9版本中,OpenCV在这种情况下仍会生成不正确的TIFF(尝试将TIFFTAG_COMPRESSION设置为COMPRESSION_NONE)

在查看OpenCV源代码后,我找到了两种克服此限制的方法:

  • 使用“OpenCV/modules/imgcodecs/src/grfmt_tiff.cpp”中的更改重新编译OpenCV—OpenCV中的人员添加了用于压缩的参数,但忘记了一个事实,即如果我们不希望压缩,libtiff无法在tiff句柄中设置预测器。你应该找到这个代码

    if(!TIFFSetField(pTiffHandle,TIFFTAG_IMAGEWIDTH,width)
    ||!TIFFSetField(pTiffHandle,TIFFTAG_图像长度,高度)
    ||!TIFFSetField(pTiffHandle、TIFFTAG\u BITSPERSAMPLE、bitsPerChannel)
    ||!TIFFSetField(pTiffHandle、TIFFTAG\u压缩、压缩)
    ||!TIFFSetField(pTiffHandle、TIFFTAG\u光度控制、颜色空间)
    ||!TIFFSetField(pTiffHandle、TIFFTAG_采样每像素、通道)
    ||!TIFFSetField(pTiffHandle、TIFFTAG\u PLANARCONFIG、PLANARCONFIG\u CONTIG)
    ||!TIFFSetField(pTiffHandle,TIFFTAG_ROWSPERSTRIP,ROWSPERSTRIP)
    ||!TIFFSetField(pTiffHandle、TIFFTAG\u预测器、预测器)
    )
    {
    TIFFClose(pTiffHandle);
    返回false;
    }

    并将其更改为

    if(!TIFFSetField(pTiffHandle,TIFFTAG_IMAGEWIDTH,width)
    ||!TIFFSetField(pTiffHandle,TIFFTAG_图像长度,高度)
    ||!TIFFSetField(pTiffHandle、TIFFTAG\u BITSPERSAMPLE、bitsPerChannel)
    ||!TIFFSetField(pTiffHandle、TIFFTAG\u压缩、压缩)
    ||!TIFFSetField(pTiffHandle、TIFFTAG\u光度控制、颜色空间)
    ||!TIFFSetField(pTiffHandle、TIFFTAG_采样每像素、通道)
    ||!TIFFSetField(pTiffHandle、TIFFTAG\u PLANARCONFIG、PLANARCONFIG\u CONTIG)
    ||!TIFFSetField(pTiffHandle,TIFFTAG_ROWSPERSTRIP,ROWSPERSTRIP)
    )
    {
    TIFFClose(pTiffHandle);
    返回false;
    }
    如果(压缩)=压缩\u无
    &&!TIFFSetField(pTiffHandle、TIFFTAG\u预测器、预测器)
    )
    {
    TIFFClose(pTiffHandle);
    返回false;
    }
    

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

  • 另一种方法是在应用程序中直接使用libtiff保存TIFF。当然,在这种情况下需要实现写函数。对于windows,您应该编译libtiff,但这是一项相当简单的任务(libtiff包含许多编译器的makefile,并且可以在MinGW和MSVC、32位和64位中完美编译)


  • 如果其他任何人发现avtomaton的解决方案似乎是通过pull请求添加的

    允许您执行以下操作(适用于3.2):

    cv::Mat短裤(1024*cv::Mat::one(100100,cv16uc1));
    向量标记={TIFFTAG\u COMPRESSION,COMPRESSION\u NONE};
    bool success=cv::imwrite(“uncompressed.tif”、短裤、标签);
    
    为什么人们对这个问题投反对票?@onitake我没有,但我只能假设,因为OP似乎在问一个基本问题,而没有做家庭作业。根据常见问题解答的条目,用户需要在此处提问之前彻底研究问题,并在问题中分享他们的结果。不这样做可能会导致该问题获得否决票和接近票。我不能说我完全不同意他们的观点。你应该查看OpenCV的源代码。许多这样的高级功能都是可用的,但没有文档记录。也许imwrite的一些额外参数会让你到达那里也许OP没有搜索,但这不是一个简单的问题。很好的发现!谷歌似乎忘记了最近的文档?
    IplImage* image = cvCreateImage(cvSize(100,100),16,1);
    memset(image->imageData,someData,image->width*image->height*2);
    cvSaveImage("image.png",image);
    
    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);