我使用OpenCV/C++来计算两幅图像之间的相似率。 我想告诉用户%图像A看起来像图像B。
我们来看看下面的代码:
double getSimilarityRate(const cv::Mat A, const cv::Mat B){
double cpt = 0.0;
cv::Mat imgGray1, imgGray2;
cv::cvtColor(A, imgGray1, CV_BGR2GRAY);
cv::cvtColor(B, imgGray2, CV_BGR2GRAY);
imgGray1 = imgGray1 > 128;
imgGray2 = imgGray2 > 128;
double total = imgGray1.cols * imgGray1.rows;
if(imgGray1.rows > 0 && imgGray1.rows == B.rows && imgGray1.cols > 0 && imgGray1.cols == B.cols){
for(int rows = 0; rows < imgGray1.rows; rows++){
for(int cols = 0; cols < imgGray1.cols; cols++){
if(imgGray1.at<int>(rows, cols) == imgGray2.at<int>(rows,cols)) cpt ++;
}
}
}else{
std::cout << "No similartity between the two images ... [EXIT]" << std::endl;
exit(0);
}
double rate = cpt / total;
return rate * 100.0;
}
int main(void)
{
/* ------------------------------------------ # ALGO GETSIMILARITY BETWEEN 2 IMAGES # -------------------------------------- */
double rate;
string fileNameImage1("C:\\Users\\hugoo\\Documents\\Prog\\NexterMU\\Qt\\OpenCV\\DetectionShapeProgram\\mire.jpg");
cv::Mat image1 = imread(fileNameImage1);
string fileNameImage2("C:\\Users\\hugoo\\Documents\\Prog\\NexterMU\\Qt\\OpenCV\\DetectionShapeProgram\\mire.jpg");
cv::Mat image2 = imread(fileNameImage2);
if(image1.empty() || image2.empty()){
std::cout << "Images couldn't be loaded" << std::endl;
exit(-1);
}
rate = getSimilarityRate(image1, image2) ;
首先,我将矩阵从BGR转换为灰度。 所以我只剩下一个频道了。 (比较起来要容易得多)。
cv::Mat imgGray1, imgGray2;
cv::cvtColor(A, imgGray1, CV_BGR2GRAY);
cv::cvtColor(B, imgGray2, CV_BGR2GRAY);
然后我将它们设置为二进制(255或0-->像素的白色或黑色):
imgGray1 = imgGray1 > 128;
imgGray2 = imgGray2 > 128;
在我的for循环中,我通过每个像素,并将他与第二幅图像中的其他像素进行比较。 如果匹配,我增加一个变量(cpt++)。
我计算速率并将其转换为%,其中:
double rate = cpt / total;
return rate * 100.0;
问题是它似乎计算不正确,因为它没有返回控制台中的速率值。。。
输出控制台
我认为问题来自于at()函数,也许我没有正确使用它。
如果有人能引导我度过难关,帮我解决这个问题,我会很感激的。
如果你需要更多的信息,告诉我:)。
谢谢。
我怀疑imggray1.at
应该改为imggray1.at
。
当前.at()
函数调用具有int
作为模板参数,但通常cv::mat
由uchar
元素组成。 您确定您的映像包含int
元素吗? 如果它确实由uchar
元素组成,那么使用int
模板参数将导致访问超出与图像对应的内存(基本上所有指针偏移量现在都是应该的4倍)。
更一般地,如果使用cv::mat::at()
,则需要根据cv::mat::type()
的输出使用不同的模板参数:
.at(行,列)
.at(row,column)
.at(行,列)
.at(row,column)
因此,如果函数应该支持任意的cv::mat
,则需要编写一组if-else子句,或者完全避免.at()
。 在您的情况下,由于imggray1
和imggray2
是“二进制化”的,我想知道是否可以使用CV::Norm计算速率
,可能如下:
// NORM_INF counts the number of non-equal elements.
int num_non_equal = cv::norm(imgGray1, imgGray2, NORM_INF);
double rate = 1.0 - num_non_equal / static_cast<double>(total);