saidinsan000000000 Ответов: 4

Калькулятор средних и дисперсий


Всем привет, после компиляции исходного кода я получил нулевую дисперсию. этот результат верен или нет?
Заранее спасибо

Что я уже пробовал:

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/core/mat.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include<iostream>
#include<math.h>
#include<time.h>
using namespace std;
using namespace cv;

int main(int argc, char *argv[])
{
system("clear");
Mat src=imread("/home/Adam/Bureau/2.jpg",0);
float mean,s,v,e;
int a=src.rows, b=src.cols;
time_t t;
srand((unsigned) time(&t));
for(int i=0;i<src.rows;i++){
for(int j=0;i<src.cols;j++){ s+=src.at<float>(i,j);
mean=s/(a*b);
e+=(src.at<float>(i,j)-mean)*(src.at<float>(i,j)-mean);
v=e/(a*b);
}
}
cout<<"the mean ="<<mean<<endl;
cout<<"la variance est ="<<v<<endl;
return 0;
}

4 Ответов

Рейтинг:
2

CPallini

В любом случае ваше вычисление дисперсии неверно.
Ты должен первый вычислите среднее значение и затем используйте вычисленное среднее значение для вычисления дисперсии. То есть вам нужны две петли.


saidinsan000000000

спасибо

CPallini

Добро пожаловать.

Рейтинг:
2

Jochen Arndt

Среднее значение, используемое вашим кодом в циклах для вычисления дисперсии, является не окончательным, а тем, которое уже было обработано для обрабатываемых элементов. Вы также не инициализировали переменные суммы s и e с нуля.

Сначала вы должны вычислить среднее значение, а затем использовать другую итерацию для вычисления дисперсии:

// Use double to reduce inaccuray and initialise start value
double mean = 0;
for (int i = 0; i < src.rows; i++)
{
    for (int j = 0; j < src.cols; j++)
        mean += src.at<uchar>(i, j);
}
mean /= a * b;

// Calculate variance now using the final mean
double v = 0;
for (int i = 0; i < src.rows; i++)
{
    for (int j = 0; j < src.cols; j++)
        v += (src.at<uchar>(i, j) - mean) * (src.at<uchar>(i, j) - mean);
}
// Variance
v /= a * b;
// Sample variance
//v /= (a * b) - 1;

[РЕДАКТИРОВАТЬ]
Есть еще одна проблема:
Вы используете src.at<float>(i, j) чтобы получить значения пикселей из изображения. Но вы уже прошли 0 в качестве второго параметра к imread который IMREAD_GRAYSCALE. Тогда матрица содержит uchar значения для каждого пикселя, определяющие интенсивность. Этот тип должен использоваться при доступе к пикселям.
[/РЕДАКТИРОВАТЬ]


saidinsan000000000

спасибо за ваш ответ но этот код не дает никакого результата

Jochen Arndt

Что вы подразумеваете под "отсутствием результата"?
среднее и v будут содержать значение, которое является результатом. Я не испытывал его. Таким образом, это может дать не правильный результат (но это должно быть).

saidinsan000000000

Я имею в виду, что это дает неверный результат

saidinsan000000000

спасибо за вашу реакцию, после компиляции я получаю "среднее значение равно-НАН!!!!

Jochen Arndt

Это, вероятно, потому, что в вашем коде есть еще одна ошибка, которую я скопировал и вставил. Линия(ы)
Скрыть   скопировать код

for (int j = 0; i < src.cols; j++)

должно быть 'j' для конечного условия:
Скрыть   скопировать код
for (int j = 0; j < src.cols; j++)

Я исправлю это в своем ответе.

Однако эта ошибка должна привести к бесконечному циклу, который может быть остановлен только нарушением доступа.

Я также не знал OpenCV достаточно хорошо, чтобы знать, используется ли он
Mat::at<double>(row, col);<pre>
is correct. You might check that and use <float> if that would be correct (assigning / adding a float to a double needs no cast).

Jochen Arndt

Смотрите мой обновленный ответ.
Я читал об OpenCV и imread. Вы должны использовать правильный тип при доступе к пикселям.

saidinsan000000000

спасибо за ваш ответ, я последовал вашему совету, но в конце концов получил среднее значение, равное нулю

Jochen Arndt

Я не запускал код (требуется установка OpenCV).
Вы должны проверить, верны ли мои предположения о доступе к мату.
Вы можете сделать это, просто распечатав некоторые значения пикселей (они должны быть от 0x00 до 0xff). Если это так, то среднее значение должно быть в том же диапазоне, а не нулевым (при условии, что изображение не все черное).

saidinsan000000000

спасибо

Рейтинг:
1

KarstenK

Сначала вы должны инициализировать каждую переменную как mean to e с 0. Значение из доступа к src.at<float>(i,j) должно храниться в var.

Логика вашей программы выглядит странно. При каждом взаимодействии i и j вы меняете среднее значение. Я думаю, что вы должны зациклиться на всех пикселях и суммировать их, чтобы построить среднее значение. Чем петля для дисперсии.

Читайте основные сведения о компании различие чтобы доказать, что ваш расчет-это то, что вы хотите.


saidinsan000000000

спасибо

Рейтинг:
0

Patrice T

Научитесь правильно делать отступы в вашем коде, это покажет его структуру, и это поможет чтению и пониманию.

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/core/mat.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include<iostream>
#include<math.h>
#include<time.h>
using namespace std;
using namespace cv;

int main(int argc, char *argv[])
{
  system("clear");
  Mat src=imread("/home/Adam/Bureau/2.jpg",0);
  float mean,s,v,e;
  int a=src.rows, b=src.cols;
  time_t t;
  srand((unsigned) time(&t));
  for(int i=0;i<src.rows;i++){
    for(int j=0;i<src.cols;j++){ // do not pack many things on same line of code
       s+=src.at<float>(i,j);    // it just make it more difficult to read.
      mean=s/(a*b);
      e+=(src.at<float>(i,j)-mean)*(src.at<float>(i,j)-mean);
      v=e/(a*b);
    }
  }
  cout<<"the mean ="<<mean<<endl;
  cout<<"la variance est ="<<v<<endl;
  return 0;
}

Профессиональные редакторы программистов имеют эту функцию и другие, такие как сопоставление скобок и подсветка синтаксиса.
Блокнот++ Главная Страница[^]
личные[^]

вам нужно прочитать о C++ делении целых чисел

Когда вы не понимаете, что делает ваш код или его результаты, ответ заключается в том, что debuggern позволяет вам точно видеть, что делает ваш код, и проверять переменные, которые он выполняет.

Существует инструмент, который позволяет вам видеть, что делает ваш код, его имя отладчик Это также отличный инструмент обучения, потому что он показывает вам реальность, и вы можете увидеть, какие ожидания соответствуют реальности.
Когда вы не понимаете, что делает ваш код или почему он делает то, что он делает, ответ таков: отладчик.
Используйте отладчик, чтобы увидеть, что делает ваш код. Просто установите точку останова и посмотрите, как работает ваш код, отладчик позволит вам выполнять строки 1 на 1 и проверять переменные по мере их выполнения.

Отладчик - Википедия, свободная энциклопедия[^]

Освоение отладки в Visual Studio 2010 - руководство для начинающих[^]
Базовая отладка с помощью Visual Studio 2010 - YouTube[^]
Отладчик здесь, чтобы показать вам, что делает ваш код, и ваша задача-сравнить с тем, что он должен делать.
В отладчике нет никакой магии, он не находит ошибок, он просто помогает вам. Когда код не делает того, что ожидается, вы близки к ошибке.