OpenCV 3.4将PGM图像从CV_8UC1转CV_32SC1时像素全为0的问题
解决OpenCV 3.4中PGM转CV_32SC1后像素值异常的问题
我之前在处理PGM图像转32位整数格式时也踩过类似的坑,咱们一步步拆解下你遇到的问题:
首先,先明确两个核心点:
- PGM格式(不管是ASCII的P2还是二进制的P5),OpenCV默认用
IMREAD_GRAYSCALE读取后会变成CV_8UC1(8位无符号单通道)格式,像素值范围是0-255。 - OpenCV的
convertTo函数做类型转换时,默认不会自动缩放像素值范围——它只是把当前数值直接转换成目标类型的数值,不会做任何比例映射。
为什么你会看到所有像素值相同(比如74)?
这大概率不是转换的问题,先排查这几点:
先确认读取的原图像是否正常
先打印原图像的类型和像素范围,看看是不是读取的图像本身就是全74的:cv::Mat img = cv::imread("your_image.pgm", cv::IMREAD_GRAYSCALE); if (img.empty()) { std::cerr << "Failed to read image!" << std::endl; return -1; } // 打印原图像类型 std::cout << "Original type: " << img.type() << std::endl; // 打印原图像的最小/最大像素值 double min, max; cv::minMaxLoc(img, &min, &max); std::cout << "Original pixel range: " << min << " ~ " << max << std::endl;如果原图像的min和max都是74,那说明你读取的PGM文件本身就是这样的,和转换无关。
检查转换代码是否正确
正确的转换CV_32SC1的代码应该是这样的:cv::Mat imgConv; // 直接转换,默认scale=1,shift=0 img.convertTo(imgConv, CV_32SC1);如果你不小心加了
scale=0或者错误的shift值,才会导致像素全变成0,但你说结果是74,这应该不是这个问题。
关于“像素自动转换到32位范围”的误解
你以为的“自动转换到32位范围”应该是指把0-255映射到32位整数的全范围(-231到231-1),但OpenCV不会默认这么做——它只会做类型的强制转换,比如8位的74直接变成32位整数的74,数值本身不变。
如果确实需要把0-255的像素值映射到32位整数的某个范围(比如0到2147483647),才需要手动设置scale参数:
// 把0-255映射到0到2^31-1(32位有符号整数的最大值) img.convertTo(imgConv, CV_32SC1, (2147483647.0)/255.0);
不过一般来说,这种映射是没必要的,除非你的后续算法要求必须用32位的全范围数值。
关于imshow显示的坑
另外,用imshow显示CV_32SC1格式的图像时,OpenCV会自动把像素值缩放到0-255的范围来显示。比如如果你的32位图像里的数值都是74,显示出来就是统一的灰色;如果数值是2147483647,显示出来就是纯白色。所以不要只靠imshow判断像素值,一定要用at<int>(y,x)或者minMaxLoc来实际查看数值。
内容的提问来源于stack exchange,提问作者Martin Herrmann
相关产品推荐
相关产品推荐

