MySQL 在(pure) PHP/MySQL中查找相似的图像
阅读更多:MySQL 教程
前言
现代计算机视觉领域的出现以及物联网的发展都导致了大量图像的生成、传输和存储。同时,通过这些图像,我们可以获得很多有价值的信息分析。
对于分类和识别这样的任务来说,找到一堆相似的图像是一个非常重要的部分。比如在交通管理中,我们需要识别交通信号灯或汽车。如果我们的数据库中有数以千计的图像需要识别,那么找到一个相似的图像将会给我们节省大量处理时间。
在本文中,我们将介绍如何在 PHP 和 MySQL 中查找相似的图像,这将帮助您解决您的计算机视觉问题。
原理
我们基于已有数据查找相似图像,我们需要:
– 将查询图像的特征(例如颜色、大小、边缘等)与存储在数据库中的图像进行比较
– 通过比较测量查询图像与现有图像之间的相似度
– 使用这些相似度确定哪些图像与查询图像相似
环境
在开始之前,您需要有以下环境才能尝试本文中的例子:
– PHP > 5
– MySQL > 5.5
– OpenCV > 2.4.2
步骤
下面我们将展示如何做到这一点:
1.提取消息和预处理图像
首先,我们必须知道如何提取和预处理图像。要提取这些特征,我们将使用 OpenCV 的库。
2.从图像提取特征
在这一步中,我们需要从图像中提取一些特定的特征。我们将使用 OpenCV 初始化,然后使用 OpenCV 的提取函数来获得与图像相关的特征。
颜色
在这个例子中,我们将提取颜色特征。首先,我们需要把 RGB 图像转换成 HSV 颜色模型:
$img = imagecreatefromjpeg('image.jpg');
imagefilter($img, IMG_FILTER_GRAYSCALE);
for ($x = 0; $x < imagesx($img); $x++) {
for ($y = 0; $y < imagesy($img); $y++) {
$rgb = imagecolorat($img, $x, $y);
$r = ($rgb >> 16) & 0xFF;
$g = ($rgb >> 8) & 0xFF;
$b = $rgb & 0xFF;
$hsv = rgb2hsv($r, $g, $b);
$hue = floor($hsv[0] / 10);
$saturation = floor($hsv[1] / 10);
$value = floor($hsv[2] / 10);
$histogram[$hue][$saturation][$value]++;
}
}
其中,rgb2hsv 函数表示:
function rgb2hsv(r,g, b) {h = 0;
s = 0;v = 0;
rgbMax = max(r, g,b);
rgbMin = min(r, g,b);
rgbDiff =rgbMax - rgbMin;
if (rgbMin == rgbMax) {h = 0;
} else if (rgbMax ==r) {
h = (g - b) /rgbDiff;
h *= 60;
if (h < 0) {
h += 360;
}
} else if (rgbMax == g) {h = (b -r) / rgbDiff;h *= 60;
h += 120;
} else if (rgbMax == b) {h= (r -g) / rgbDiff;h *= 60;
h += 240;
}v = rgbMax;
if (rgbMax == 0) {
s = 0;
} else {s = (rgbDiff /rgbMax) * 100;
}
hsv[0] =h;
hsv[1] =s;
hsv[2] =v;
return $hsv;
}
现在我们可以使用一个数组来存储颜色特征。
形状
此外,我们可以提取轮廓形状特征。我们可以使用 OpenCV 的轮廓检测功能来实现它。
3.计算相似性度量值
有了我们的特征向量,我们现在可以在数据库中查找与查询向量“最接近”的向量。这个过程可以被建模成向量空间查找问题。
面对这个问题,最常用的方法是计算两个向量之间的欧几里得距离。
而在 MySQL 中,由于计算每个向量之间的距离非常耗时,我们将使用比欧几里得距离更快的余弦相似度。
余弦相似度的原理是:对于两个向量 a 和 b,余弦相似度度量它们之间的夹角和互相重合的程度。它的值不能超过1,如果两个向量完全相同,则相似度为1,如果向量完全反向,则相似度为-1,如果两个向量毫无关系,则相似度为0。设两个向量 a 和 b 的点积为 a\cdot b , a 的长度为 ||a|| ,则两个向量之间的余弦相似度是:
\text{similarity}=\cos(\theta)=\frac{a\cdot b}{||a||||b||}=\frac{\sum\limits_{i=1}^{n}a_i \cdot b_i}{\sqrt{\sum\limits_{i=1}^{n}(a_i)^2}\cdot \sqrt{\sum\limits_{i=1}^{n}(b_i)^2}}
4.存储图像和计算特征
在这一步中,我们需要缓慢地存储所有图像和其特征。
为了获得最好的性能,我们可以使用嵌套的散列表,其中第一级散列表为特征值创建散列,第二级散列表则存储与这些特征值对应的图像。
5.查找相似图像
如果我们有了一个查询图像和其特征向量,那么要查找与其相似的其他图像,我们只需:
- 计算查询特征向量与数据库中所有图像的特征向量之间的余弦相似度
- 将这些相似度排序
- 返回相似度最高的 n 个图像
这个过程可以在 MySQL 中使用 SQL 查询来实现。
结论
在这篇文章中,我们讨论了如何使用 PHP 和 MySQL 来查找相似的图像。我们介绍了一些提取图像特征的方法,并展示了如何使用余弦相似度来计算相似性。我们还提供了查找相似图像的步骤。这些知识可以帮助您在计算机视觉领域中的分类和识别这样的任务中找到相似图像。