1.概要
需求:
判断一个物体是啥,其实就是一个东西属于哪一类,就是这些都东西都有那些特征,这些特征的相似度是多少,最终分成不同的类别。
理解:
其实特征检测有各种各样的算法,但是视觉的世界无非点、线、面;如果依据这些东西找到相似性就是智能了;各种检测算法是如何的组织点线面,并把这些东西,变成特征的呢?更单纯的关系是像素关系,像素有什么关系呢?位置关系,相邻;本身属性,相似,比如1、7、256三个数分成两类怎么分呢,很好分,1,7 和256 ;为什么这么分呢,因为1和7的数据明显更接近,这里可以证明数据本身是可以有不共的相似度的,那么有像素 到点、线、面 到更丰富的特征属性也都是可以用数据确认相似度的,也就最终构成了图片的相似度,物体的相似度,进而进行图像分类或者物体识别。到了数的层面,一切的关系就都可以用数衡量了,这也是把图片变成数据,变成可以判断的基础,在数的世界,1和1就是完全一样的,而不是这个鸡蛋与那个鸡蛋完全不同,进入数据的层面,相同的数完全相同,没有个性,而不同的数据构成更复杂的维度,就构造一个无线精彩的世界,这也是数能模拟一切的基础;不同的算法就是依据数本身的基础属性,用不同的维度,构造更更复杂的数据结果,就是用不同的算法对这个世界的理解;本质上确实一切都是算法,包括我们眼睛看到的东西也都是一样;世界可算、视觉可算、这就是物体识别的基础。
2.举例
用特征检测,可以确认两张图片的相似度吗,请举例,并提供代码
python 版本
使用特征检测确实可以确认两张图片的相似度。以下是一个使用OpenCV库中的ORB(Oriented FAST and Rotated BRIEF)特征检测算法来比较两张图片相似度的Python代码示例。
首先,确保你已经安装了OpenCV库。如果没有,可以通过pip安装:
pip install opencv-python |
然后,你可以使用以下代码:
#include <opencv2/opencv.hpp>
#include <vector>
#include <iostream>
int main() {
// 加载两张待比较的图片
cv::Mat img1 = cv::imread("image1.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat img2 = cv::imread("image2.jpg", cv::IMREAD_GRAYSCALE);
// 检查图片是否加载成功
if (img1.empty() || img2.empty()) {
std::cerr << "Error: Could not load images!" << std::endl;
return -1;
}
// 初始化ORB检测器
cv::Ptr<cv::ORB> orb = cv::ORB::create();
// 检测关键点和描述符
std::vector<cv::KeyPoint> keypoints1, keypoints2;
cv::Mat descriptors1, descriptors2;
orb->detectAndCompute(img1, cv::noArray(), keypoints1, descriptors1);
orb->detectAndCompute(img2, cv::noArray(), keypoints2, descriptors2);
// 使用BFMatcher进行特征匹配
cv::BFMatcher bf(cv::NORM_HAMMING, true); // crossCheck=true
std::vector<cv::DMatch> matches;
bf.match(descriptors1, descriptors2, matches);
// 对匹配项进行排序(按距离)
std::sort(matches.begin(), matches.end(), [](const cv::DMatch& a, const cv::DMatch& b) {
return a.distance < b.distance;
});
// 计算相似度指标
// 使用匹配项的数量与较小描述符数量的比例作为相似度的粗略估计
double similarity_score = static_cast<double>(matches.size()) / std::min(descriptors1.rows, descriptors2.rows);
// 输出相似度分数
std::cout << "Similarity Score: " << similarity_score << std::endl;
// 可选:绘制匹配结果并显示
cv::Mat img_matches;
cv::drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches);
cv::imshow("Matches", img_matches);
cv::waitKey(0);
return 0;
}
在这个例子中,我们做了以下几步:
- 加载两张待比较的图片,并将它们转换为灰度图。
- 初始化ORB特征检测器,并检测两张图片中的关键点和描述符。
- 使用BFMatcher(暴力匹配器)来匹配两张图片中的描述符。
- 对匹配项进行排序,通常是根据距离(越小表示越相似)。
- 可选地,绘制前N个匹配项,以便直观地查看匹配结果。
- 计算相似度分数,这里我们简单地使用匹配项的数量与总描述符数量的比例作为相似度的粗略估计。
- 输出相似度分数,并显示匹配的图片。
请注意,这个相似度分数只是一个粗略的估计,它可能受到多种因素的影响,如图片的质量、光照条件、视角变化等。对于更精确的相似度评估,你可能需要考虑更多的因素,如匹配项的质量、分布、以及使用更高级的特征检测或匹配算法。
c++版
下面是一个使用C++和OpenCV库进行ORB特征检测,并计算两张图片相似度的代码示例。请确保你已经安装了OpenCV库,并正确配置了C++编译环境。
#include <opencv2/opencv.hpp>
#include <vector>
#include <iostream>
int main() {
// 加载两张待比较的图片
cv::Mat img1 = cv::imread("image1.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat img2 = cv::imread("image2.jpg", cv::IMREAD_GRAYSCALE);
// 检查图片是否加载成功
if (img1.empty() || img2.empty()) {
std::cerr << "Error: Could not load images!" << std::endl;
return -1;
}
// 初始化ORB检测器
cv::Ptr<cv::ORB> orb = cv::ORB::create();
// 检测关键点和描述符
std::vector<cv::KeyPoint> keypoints1, keypoints2;
cv::Mat descriptors1, descriptors2;
orb->detectAndCompute(img1, cv::noArray(), keypoints1, descriptors1);
orb->detectAndCompute(img2, cv::noArray(), keypoints2, descriptors2);
// 使用BFMatcher进行特征匹配
cv::BFMatcher bf(cv::NORM_HAMMING, true); // crossCheck=true
std::vector<cv::DMatch> matches;
bf.match(descriptors1, descriptors2, matches);
// 对匹配项进行排序(按距离)
std::sort(matches.begin(), matches.end(), [](const cv::DMatch& a, const cv::DMatch& b) {
return a.distance < b.distance;
});
// 计算相似度指标
// 使用匹配项的数量与较小描述符数量的比例作为相似度的粗略估计
double similarity_score = static_cast<double>(matches.size()) / std::min(descriptors1.rows, descriptors2.rows);
// 输出相似度分数
std::cout << "Similarity Score: " << similarity_score << std::endl;
// 可选:绘制匹配结果并显示
cv::Mat img_matches;
cv::drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches);
cv::imshow("Matches", img_matches);
cv::waitKey(0);
return 0;
}
在这个C++代码中,我们做了与Python示例中相似的步骤:
- 加载两张待比较的图片,并将它们转换为灰度图。
- 初始化ORB特征检测器。
- 检测两张图片中的关键点和描述符。
- 使用BFMatcher进行特征匹配。
- 对匹配项进行排序。
- 计算相似度分数,这里使用匹配项的数量与较小描述符数量的比例作为相似度的粗略估计。
- 输出相似度分数,并可选地绘制和显示匹配结果。
请确保将image1.jpg
和image2.jpg
替换为你实际要比较的图片文件路径。此外,你可能需要根据你的OpenCV安装和编译环境调整代码中的包含路径和链接库。
编译这个代码时,你需要链接OpenCV库。例如,如果你使用g++编译器,你可以使用类似以下的命令:
g++ -o compare_images compare_images.cpp `pkg-config --cflags --libs opencv4` |
注意:pkg-config --cflags --libs opencv4
这部分取决于你的OpenCV安装和版本。如果你使用的是OpenCV 3或其他版本,你可能需要相应地调整pkg-config
命令或手动指定编译和链接选项。