不同的像素值在MATLAB和c++与OpenCV
Different Pixel Values in MATLAB and C++ with OpenCV
我看到有类似的问题,但不要安静地回答我的问题,所以这是我的问题。
在c++和OpenCV中,我运行下面的代码,它返回6.32的平均像素值。然而,当我打开图像并在MATLAB中使用mean函数时,它返回大约6.92ish的平均像素强度。正如你所看到的,我将OpenCV值转换为double,以试图缓解这个问题,并发现OpenCV将图像加载为一组整数,而MATLAB将图像加载为十进制值,这些值近似但不完全相同,显然与整数相同。所以我的问题是,作为编程新手,哪个是正确的?我假设MATLAB返回更准确的值,如果是这种情况,我想知道是否有方法以相同的方式加载图像以避免差异。
谢谢,下面的代码
Mat img = imread("Cells2.tif");
cv::cvtColor(img, img, CV_BGR2GRAY);
cv::imshow("stuff",img);
Mat dst;
if(img.channels() == 3)
{
img.convertTo(dst, CV_64FC1);
}
else if (img.channels() == 1)
{
img.convertTo(dst, CV_64FC1);
}
cv::imshow("output",dst/255);
int NumPixels = img.total();
double avg;
double c = 0;
double std;
for(int y = 0; y < dst.cols; y++)
{
for(int x = 0; x < dst.rows; x++)
{
c+=dst.at<double>(x,y)*255;
}
}
avg = c/NumPixels;
cout << "asfa = " << c << endl;
double deviation;
double var;
double z = 0;
double q;
//for(int a = 0; a<= img.cols; a++)
for(int y = 0; y< dst.cols; y++)
{
//for(int b = 0; b<= dst.rows; b++)
for(int x = 0; x< dst.rows; x++)
{
q=dst.at<double>(x,y);
deviation = q - avg;
z = z + pow(deviation,2);
//cout << "q = " << q << endl;
}
}
var = z/(NumPixels);
std = sqrt(var);
cv::Scalar avgPixel = cv::mean(dst);
cout << "Avg Value = " << avg << endl;
cout << "StdDev = " << std << endl;
cout << "AvgPixel =" << avgPixel;
cvWaitKey(0);
return 0;
}
根据您的评论,该图像似乎以16位深度存储。MATLAB按原样加载TIFF图像,而默认情况下OpenCV将以8位加载图像。这也许可以解释你所看到的精度差异。
使用以下命令在OpenCV中打开图像:
cv::Mat img = cv::imread("file.tif", cv::IMREAD_ANYDEPTH|cv::IMREAD_ANYCOLOR);
在MATLAB中,它很简单:
img = imread('file.tif');
接下来,您需要了解正在使用的数据类型。在OpenCV中它的CV_16U,在MATLAB中它的uint16
。因此,您需要相应地转换类型。
img2 = double(img) ./ double(intmax('uint16'));
将其转换为值在[0,1]范围内的double
图像
加载图像时,必须在两种环境(MATLAB和OpenCV)中使用类似的方法,以避免在两种环境中默认情况下可能完成的转换
- 如果满足某些条件,您正在转换图像,这可以改变一些颜色值,而MATLAB可以选择不转换图像,而是使用原始图像
-
颜色与流行的实现大多用十六进制格式表示0 xaarrggbb或0 xrrggbbaa的格式,所以32位整数会(无符号/签署无所谓,十六进制值仍然是相同的),创建一个64位变量,把所有32位变量加起来,然后除以像素的数量,这将给你一个很准确的结果(为16384×16384像素图像(一个32位值代表一个像素的颜色),如果更大,那么64位整数将不够)。
long long total = 0; long long divisor = image.width * image.height; for(int x = 0; x < image.width; ++x) { for(int y = 0; x < image.height; ++x) { total += image.at(x,y).color; } } double avg = total / divisor; std::cout << "Average color value: " << avg << std::endl;
不确定您在Matlab与OpenCV中的平均值有什么困难。如果我正确理解你的问题,你的目标是在OpenCV中实现Matlab的mean(image(:))
。例如,在Matlab中,您可以执行以下操作:
>> image = imread('sheep.jpg')
>> avg = mean(image(:))
ans =
119.8210
下面是你如何在OpenCV中做同样的事情:
Mat image = imread("sheep.jpg");
Scalar avg_pixel;
avg_pixel = mean(image);
float avg = 0;
cout << "mean pixel (RGB): " << avg_pixel << endl;
for(int i; i<image.channels(); ++i) {
avg = avg + avg_pixel[i];
}
avg = avg/image.channels();
cout << "mean, that's equivalent to mean(image(:)) in Matlab: " << avg << endl;
OpenCV控制台输出
mean pixel (RGB): [77.4377, 154.43, 127.596, 0] mean, that's equivalent to mean(image(:)) in Matlab: 119.821
因此在Matlab和OpenCV中结果是相同的。
跟进在你的代码中发现一些问题。
OpenCV存储数据与Matlab不同。看看这个关于如何在OpenCV中访问像素的粗略解释。例如:
// NOT a correct way to access a pixel in CV_F32C3 type image double pixel = image.at<double>(x,y); //The correct way (where the pixel value is stored in a vector) // Note that Vec3d is defined as: typedef Vec<double, 3> Vec3d; Vec3d pixel = image.at<Vec3d>(x, y);
我发现了另一个错误
if(img.channels() == 3) { img.convertTo(dst, CV_64FC1); //should be CV_64FC3, instead of CV_64FC1 }
访问Mat
元素可能会混淆。我建议从一本关于OpenCV的书开始,例如这本书,并阅读OpenCV教程和文档。
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 尝试导入pybind-opencv模块时出现libgtk错误
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- OpenCV EqualizeHist()从彩色图像创建黑白图像
- 将OpenCV C++重写为EmguCV C#-如何使用指针
- OpenCV C++.快速计算混淆矩阵
- 在C++代码中包含opencv时,使用ctypes创建.so文件
- 哪些库可以通过Opencv调整曝光率
- 安装opencv失败-粘贴CMakeError.log的内容
- C++中的openCV Mat访问冲突
- OpenCV Android C++ imwrite not found
- 未定义的引用 .. 使用 OpenCV 编译 C++ 代码时,从命令行
- 将 OpenCV 与 CMAKE 中的项目一起构建为第三方库的正确方法
- CV_OCL_RUN宏如何在OpenCV(版本3.4.5)的goodFeaturesToTrack实现中工作?
- OpenCV 4.1.2 - 从网络摄像头获取帧并将其拆分
- C++ OpenCV 卡尔曼滤波器构造函数错误
- 使用OpenCV和覆盆子上的多个网络摄像头拍摄延时摄影,出现多个V4L错误
- 如何使用OpenCV-C++编写*.mp4视频?
- Mingw-64 在构建和安装后不会编译 openCV 代码