Я работаю над проектом, который обнаруживает некоторые особенности двух входных изображений (рукописные подписи) и сравнивает эти две функции, используя косинусное сходство. Здесь Когда я имею в виду два входных изображения, одно является исходным изображением, а другое является дублированным изображением.
Скажем, я извлекаю 15 таких функций из одного изображения (исходного изображения) и сохраняю его в одном массиве (скажем, Array_ORG), а функции другого изображения сохраняются в Array_DUP аналогичным образом.
Теперь я пытаюсь вычислить косинусное сходство между этими двумя массивами. Эти массивы имеют двойной тип данных.
Я перечисляю два метода, которым я следовал:
1) Ручной расчет косинуса подобия:
main(){
for(int i=0;i<15;i++)
sum_org += (Array_org[i]*Array_org[i]);
for(int i=0;i<15;i++)
sum_dup += (Array_dup[i]*Array_dup[i]);
double magnitude = sqrt(sum_org +sum_dup );
double cosine_similarity = dot_product(Array_org, Array_dup, sizeof(Array_org)/sizeof(Array_org[0]))/magnitude;
}
double dot_product(double *a, double* b, size_t n){
double sum = 0;
size_t i;
for (i = 0; i < n; i++) {
sum += a[i] * b[i];
}
return sum;
}
2) Сохранение значений в Mat и вызов функции точки:
Mat A = Mat(1,15,CV_32FC1,&Array_org);
Mat B = Mat(1,15,CV_32FC1,&Array_dup);
double similarity = cal_theta(A,B);
double cal_theta(Mat A, Mat B){
double ab = A.dot(B);
double aa = A.dot(A);
double bb = B.dot(B);
return -ab / sqrt(aa*bb);
}
Я читал, что значение косинуса сходства варьируется от -1 до 1, где -1 говорит, что оба абсолютно противоположны, и 1, что оба равны. Но первая функция дает мне значения в тысячах, а вторая функция дает мне значения больше 1.
Пожалуйста, объясните мне, какой процесс является правильным и почему?
Кроме того, как вывести сходство, если значения косинуса сходства больше 1?
Правильное определение косинусного сходства:
Ваш код не вычисляет знаменатель, поэтому значения неверны.
double cosine_similarity(double *A, double *B, unsigned int Vector_Length)
{
double dot = 0.0, denom_a = 0.0, denom_b = 0.0 ;
for(unsigned int i = 0u; i < Vector_Length; ++i) {
dot += A[i] * B[i] ;
denom_a += A[i] * A[i] ;
denom_b += B[i] * B[i] ;
}
return dot / (sqrt(denom_a) * sqrt(denom_b)) ;
}