C++读取非标准12位深度TIFF图像的方案求助
读取12位单通道无压缩TIFF图像的问题
我最近在处理高速相机生成的12位单通道无压缩TIFF图像,测试OpenCV、libTIFF、TinyTIFF均失败,报错信息统一为“仅支持8、16、24或32位TIFF”。
我目前有两个思路:
- 直接将文件作为二进制读取后处理,但不清楚具体实现方法
- 使用ImageMagick的convert工具将通道深度转为16位,但需要处理数十万张图像,两次读写(转换+后处理)效率极低,因此不想采用该方案
复现错误的libTIFF示例代码
TIFF* tif = TIFFOpen(imageName.c_str(), "r"); // Create a matrix to hold the tif image in Mat image; // check the tif is open if (tif) { do { unsigned int width, height; uint32* raster; // get the size of the tiff TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height); uint npixels = width * height; // get the total number of pixels raster = (uint32*)_TIFFmalloc(npixels * sizeof(uint32)); // allocate temp memory (must use the tiff library malloc) if (raster == NULL) // check the raster's memory was allocaed { TIFFClose(tif); throw bad_alloc(); } // Check the tif read to the raster correctly if (!TIFFReadRGBAImage(tif, width, height, raster, 0)) { TIFFClose(tif); throw runtime_error("Could not read the TIF appropriately"); } image = Mat(width, height, CV_8UC4); // create a new matrix of w x h with 8 bits per channel and 4 channels (RGBA) // iterate over all the pixels of the tif for (uint x = 0; x < width; x++) for (uint y = 0; y < height; y++) { uint32& TiffPixel = raster[y * width + x]; // read the current pixel of the TIF Vec4b& pixel = image.at<Vec4b>(Point(y, x)); // read the current pixel of the matrix pixel[0] = TIFFGetB(TiffPixel); // Set the pixel values as BGRA pixel[1] = TIFFGetG(TiffPixel); pixel[2] = TIFFGetR(TiffPixel); pixel[3] = TIFFGetA(TiffPixel); } _TIFFfree(raster); // release temp memory // Rotate the image 90 degrees couter clockwise image = image.t(); flip(image, image, 0); imshow("TIF Image", image); // show the image waitKey(0); // wait for anykey before displaying next } while (TIFFReadDirectory(tif)); // get the next tif TIFFClose(tif); // close the tif file }
补充信息(编辑1)
所有图像均来自同一款高速相机,位深度一致且未压缩。用tiffinfo工具查看任意一张图像的输出如下:
=== TIFF directory 0 === TIFF Directory at offset 0x22f5e (143198) Image Width: 258 Image Length: 370 Bits/Sample: 12 Compression Scheme: None Photometric Interpretation: min-is-black Orientation: row 0 top, col 0 lhs Samples/Pixel: 1 Rows/Strip: 21 Planar Configuration: single image plane
ImageMagick API尝试(编辑2)
我尝试用ImageMagick API读取图像,假设它支持任意位深度的TIFF,但调用read方法后得到的是零尺寸图像,未抛出异常,问题仍未解决:
// Create base image Image image; Mat cvImage; try{ image.read(imageName); // Set the image type to TrueColor DirectClass representation. image.type(GrayscaleType); // Ensure that there is only one reference to underlying image // If this is not done, then image pixels will not be modified. //image.modifyImage(); // Allocate pixel view Pixels view(image); // Set all pixels in region anchored at 38x36, with size 160x230 to green. size_t columns = view.columns(); size_t rows = view.rows(); cvImage = Mat(columns, rows, CV_8UC(1)); // create a new matrix of w x h with 8 bits per channel and 4 channels (RGBA) Quantum* pixels = view.get(0, 0, columns, rows); for (ssize_t row = 0; row < rows; ++row) for (ssize_t column = 0; column < columns; ++column) { uchar& pixel = cvImage.at<uchar>(cv::Point(column, row)); // read the current pixel of the matrix pixel = *pixels++; // Set the pixel values as BGRA } imshow("TIF Image", cvImage); // show the image cv::waitKey(0); // wait for anykey before displaying next } catch (Magick::Exception& error_) { cout << "Caught exception: " << error_.what() << endl; }
临时解决方案(编辑3)
目前使用以下命令批量转换格式,但希望找到更高效的直接读取方案:
mogrify -format png *.tif
内容的提问来源于stack exchange,提问作者Kbzon
相关产品推荐
相关产品推荐

