3

我看到有类似的问题,但不要安静地回答我的问题,所以这是我的问题。

在带有 OpenCV 的 C++ 中,我运行下面将提供的代码,它返回的平均像素值为 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;

}

4

4 回答 4

5

根据您的评论,图像似乎以 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. 因此,您需要相应地转换类型。

例如,在 MATLAB 中:

img2 = double(img) ./ double(intmax('uint16'));

会将其转换为double值在 [0,1] 范围内的图像

于 2013-06-11T17:54:50.973 回答
0

当您加载图像时,您必须在两种环境(MATLAB 和 OpenCV)中使用类似的方法,以避免可能在任一环境中默认完成的转换。

于 2013-06-10T16:02:22.553 回答
0
  1. 如果满足某些条件,您正在转换图像,这可以改变一些颜色值,而 MATLAB 可以选择不转换图像而是使用原始图像
  2. 颜色主要以十六进制格式表示,流行的实现格式为 0xAARRGGBB 或 0xRRGGBBAA,所以 32 位整数就可以了(无符号/有符号无关,十六进制值仍然相同),创建一个 64 位变量,添加所有将 32 位变量加在一起,然后除以像素数量,这将为您提供非常准确的结果(对于高达 16384 x 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;
    
于 2013-06-10T15:56:47.943 回答
0

不确定在 Matlab 与 OpenCV 中的平均值有什么困难。如果我正确理解您的问题,您的目标是mean(image(:))在 OpenCV 中实现 Matlab。例如,在 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 教程和文档。希望这可以帮助。

于 2013-06-10T20:24:39.897 回答