ProgRoman 9 Жалоба Опубликовано January 16, 2012 Добрый день, я написал свою реализацию расстояния махаланобиса, но проект всё время падает с исключением Необработанное исключение в "0x751a9617" в "testapp.exe": Исключение Microsoft C++: cv::Exception по адресу 0x0012de30.. ниже код моего метода double calcMah(const Mat &Xk,const Mat &x) { int rw = Xk.rows; int cl = Xk.cols; Mat xm(rw,1,CV_64F); //calc mean for(int r=0; r<rw; r++) { Mat tmr = Xk.row(r).clone(); Scalar sc = mean(tmr); xm.at<double>(r) = sc.val[0]; } Mat mv = Mat::ones(rw,cl,CV_64F).mul(xm); Mat Xvg=Xk-mv; Mat cov =Xvg*Xvg.t(); Mat icov = cov.inv(); Mat res = (xm-x)*icov*(xm-x).t(); return res.at<double>(0); } Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано January 16, 2012 А падает надо думать на обращении матрицы. Или я ошибаюсь? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано January 16, 2012 нет он и без обращения падает это я специально проверял Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано January 16, 2012 без вызова этого метода проект работает нормально, поэтому я понял, что наверно проблема в самой функции Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано January 16, 2012 так сделайте cout<<"me ok"<< endl; после каждой строчки если с дебагом проблемы. Узнаете на какой ошибка. Можно еще размеры матриц вывести для контроля. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Pavia00 32 Жалоба Опубликовано January 16, 2012 Mat tmr = Xk.row(r).clone(); Н безопасный метод. У вас ошибка память выделяется, но не освобождается. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано January 17, 2012 С исключением разобрался вот нормальный код без исключений, только вот сейчас непонятно почему матрица обратная ковариационной у меня всегда получается нулевой.. double calcMah(const Mat &Xk,const Mat &x) { int rw = Xk.rows; int cl = Xk.cols; Mat xm(rw,1,CV_64F); Mat mv(rw,cl,CV_64F); //calc mean for(int r=0; r<rw; r++) { Mat tmr = Xk.row(r).clone(); Scalar sc = mean(tmr); xm.at<double>(r) = sc.val[0]; } for(int i=0; i<rw;i++) { double tempV = xm.at<double>(i); for(int j=0; j<cl;j++) { mv.at<double>(i,j)=tempV; } } Mat Xvg=Xk-mv; Mat cov =Xvg*Xvg.t(); cout<<cov<<endl; Mat icov = cov.inv(); cout<<icov<<endl; Mat diff = xm - x; cout<<diff<<endl<<diff.rows<<" | "<<diff.cols<<endl; Mat res = diff.t()*icov*diff; return res.at<double>(0); } Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано January 18, 2012 Может она и есть нулевая. Попробуйте в каком нибудь мат пакете типа MathCad или Maple то же самое сделать. Или давайте матрицу я сделаю у меня Maple установлен. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано January 18, 2012 я для тестирования использую базу данных изображений, пока просто матрица состоит из 2-х тестовых изображений и одно беру для сравнения или из этого класса или из другого.. приведу код.. я его писал для проверки расстояния махаланобиса (в матрице tempMt из которой и строится ковариационная и обратная к ней матрицы количество строк это размерность изображения вытянутого в вектор, а количество столбцов это количество этих векторов т.е. изображений) int imSz = 50;// размер изображения для тестирования Mat i1 = imread("C:/GTSRB/Final_Train/00000/00000_00026.jpg");//первое изображение из 0-го класса (тренировочное) Mat i2 = imread("C:/GTSRB/Final_Train/00000/00005_00029.jpg");//второе изображение из 0-го класса (тренировочное) Mat i3 = imread("C:/GTSRB/Final_Train/00016/00006_00028.jpg");//изображение для тестирования Mat tst; Mat tempMt(imSz*imSz,2,CV_64F); //преобразование перового изображения в вектор и запись в tempMt { Mat nts; Mat rts; Mat dts; Mat nv(imSz*imSz,1,CV_64F); cvtColor(i1,nts,CV_BGR2GRAY); resize(nts,rts,Size(imSz,imSz)); rts.convertTo(dts,CV_64F,1.0/255.0); int dx=-1; for (int r=0;r<imSz;r++ ) { for (int c=0;c<imSz;c++) { dx++; nv.at<double>(dx)=dts.at<double>(r,c); } } for(int p=0; p<imSz*imSz;p++) { tempMt.at<double>(p,0)=nv.at<double>(p); } } //преобразование второго изображения в вектор и запись в tempMt { Mat nts; Mat rts; Mat dts; Mat nv(imSz*imSz,1,CV_64F); cvtColor(i2,nts,CV_BGR2GRAY); resize(nts,rts,Size(imSz,imSz)); rts.convertTo(dts,CV_64F,1.0/255.0); int dx=-1; for (int r=0;r<imSz;r++ ) { for (int c=0;c<imSz;c++) { dx++; nv.at<double>(dx)=dts.at<double>(r,c); } } for(int p=0; p<imSz*imSz;p++) { tempMt.at<double>(p,1)=nv.at<double>(p); } } //преобразование тестового изображения в вектор, запись в tst { Mat nts; Mat rts; Mat dts; Mat nv(imSz*imSz,1,CV_64F); cvtColor(i3,nts,CV_BGR2GRAY); resize(nts,rts,Size(imSz,imSz)); rts.convertTo(dts,CV_64F,1.0/255.0); int dx=-1; for (int r=0;r<imSz;r++ ) { for (int c=0;c<imSz;c++) { dx++; nv.at<double>(dx)=dts.at<double>(r,c); } } tst = nv.clone(); } double d = calcMah(tempMt,tst); cout<<d; Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано January 18, 2012 Может быть сначала на меньших размерностях отладить? Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано January 18, 2012 пробовал сперва брать просто придуманные вектора, но тоже ничего хорошего (матрица обратная к ковариационной тоже нулевая) Mat X = (Mat_<double>(4,2)<<1,3,2,5,3,0,4,7); Mat x1 = (Mat_<double>(4,1)<<1,2,3,4); double d = calcMah(X,x1); Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано January 18, 2012 сейчас проверил в маткаде определитель ковариационной матрицы равен 0, что-то как не изменяю матрицу X он всё равно 0 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано January 18, 2012 А что у Вас является координатами точек, между которыми мы меряем расстояние? Мне кажется размерности векторов должны совпадать, а у среднего должна быть размерность пространства в котором мы работаем. А у Вас что то не то. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано January 18, 2012 почему не то у меня 4 это размерность пространства т.е. точка в R4 вот всего 2-е точки т.е. первая p1(1,2,3,4); p2(3,5,0,7), ну и точка для тестирования это x1(1,2,3,4) Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано January 18, 2012 а среднее тогда почему по рядам считаете? Mat tmr = Xk.row(r).clone(); Scalar sc = mean(tmr);[/code] Вы же вычисляете среднее между компонент вектора. У вас Входная матрица 4 ряда 2 столбца, то есть два вертикальных 4 мерных вектора. Upd: А, нет я глючусь, все вроде верно со средним. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано January 18, 2012 ну да вроде бы со средний всё нормально... считается средний вектор его размерность будет 4 строки 1 столбец вроде всё так.. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано January 18, 2012 в маткаде я подобрал точки так что бы обратная матрица к ковариационной была отлична от нуля p1(1,2,3,4);p2(3,5,0,-7); p3(5,-1,11,34);, но у меня в маткаде получился один ответ у программы совсем другой причём если при обращении поставить DECOMP_SVD т.е. Mat icov = cov.inv(DECOMP_SVD); то тоже будет другой ответ... почему что-то не особо ясно.. может ошибка где-то в функции махаланоблиса, которую я написал... Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано January 19, 2012 Легко проверить какой правильный. Перемножьте обращенную и не обращенную, получите единичную. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано January 19, 2012 вот что у меня получилось Mat X = (Mat_<double>(4,3)<<1,3,5,22,5,-1,3,20,11,4,-7,34); во вложении картинка с результатами единичной матрицы нету ни в программе ни в маткаде может это из-за того что определитель ковариационной матрицы близок к нулю... Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано January 19, 2012 У вас все элементы в матрице примерно равны. Попробуйте увеличить на порядок элементы главной диагонали, и все получится. Тут с цифрами пример: http://people.revoledu.com/kardi/tutorial/Similarity/MahalanobisDistance.html Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано January 24, 2012 Спасибо всё действительно работает!) единственно что-то уж очень долго считает на изображениях Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах