ruby - 即使一张图像的裁剪/比例略有不同,我如何检测到两张图像是 "the same"?

标签 ruby image-processing computer-vision imagemagick rmagick

我有两个不同的图像:

在 100 像素中使用 enter image description here或 400 像素 enter image description here



宽度为 100 像素 enter image description here或 400 像素 enter image description here

如您所见,从人类的角度来看,两者显然是“相同的”。现在我想以编程方式检测它们是否相同。我一直在通过名为 rmagick 的 ruby gem 使用图像魔法。像这样:

img1 = Magick::Image.from_blob(File.read("image_1.jpeg")).first
img2 = Magick::Image.from_blob(File.read("image_2.jpeg")).first

if img1.difference(img2).first < 4000.0 # I have found this to be a good threshold, but does not work for cropped images
  puts "they are the same!!!"
end

虽然这适用于具有相同比例/裁剪的图像,但当它们具有略微不同的裁剪并且已调整为相同宽度时,它并不理想。

有没有办法对不同裁剪的图像进行处理?我对一个解决方案感兴趣,我可以这样说:一个图像包含在另一个图像中,并覆盖了周围的某个地方,例如其中 90%。

PS。如果有帮助,我可以获得更高分辨率的图像(例如 double )

最佳答案

你可能想看看特征匹配。这个想法是在两个图像中找到特征并匹配它们。此方法通常用于在另一个图像中查找模板(例如 Logo )。本质上,特征可以描述为人类会在图像中发现有趣的事物,例如角落或开放空间。有许多类型的特征检测技术,但我的建议是使用尺度不变特征变换 (SIFT) 作为特征检测算法。 SIFT 对图像平移、缩放、旋转具有不变性,对光照变化部分不变,对局部几何失真具有鲁棒性。这似乎符合您的规范,其中图像的比例可能略有不同。

鉴于您提供的两个图像,这里尝试使用 FLANN feature matcher 匹配特征.为了确定这两个图像是否相同,我们可以基于某个预定阈值来确定通过 Distinctive Image Features from Scale-Invariant Keypoints by David G. Lowe 中描述的比率测试的匹配数量。 .对测试的一个简单解释是,比率测试检查匹配是否不明确并且应该被删除,您可以将其视为异常值删除技术。我们可以计算通过此测试的匹配数,以确定两个图像是否相同。以下是特征匹配结果:





Matches: 42

点代表检测到的所有匹配,而绿线代表通过比率测试的“良好匹配”。如果您不使用比率测试,则将绘制所有点。这样,您可以将此过滤器用作阈值,以仅保留最佳匹配的特征。

我用 Python 实现了它,我对 Rails 不是很熟悉。希望这有帮助,祝你好运!

代码
import numpy as np
import cv2

# Load images
image1 = cv2.imread('1.jpg', 0)
image2 = cv2.imread('2.jpg', 0)

# Create the sift object
sift = cv2.xfeatures2d.SIFT_create(700)

# Find keypoints and descriptors directly
kp1, des1 = sift.detectAndCompute(image2, None)
kp2, des2 = sift.detectAndCompute(image1, None)

# FLANN parameters
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks=50)   # or pass empty dictionary
flann = cv2.FlannBasedMatcher(index_params,search_params)
matches = flann.knnMatch(des1,des2,k=2)

# Need to draw only good matches, so create a mask
matchesMask = [[0,0] for i in range(len(matches))]

count = 0
# Ratio test as per Lowe's paper (0.7)
# Modify to change threshold 
for i,(m,n) in enumerate(matches):
    if m.distance < 0.15*n.distance:
        count += 1
        matchesMask[i]=[1,0]

# Draw lines
draw_params = dict(matchColor = (0,255,0),
                   # singlePointColor = (255,0,0),
                   matchesMask = matchesMask,
                   flags = 0)

# Display the matches
result = cv2.drawMatchesKnn(image2,kp1,image1,kp2,matches,None,**draw_params)
print('Matches:', count)
cv2.imshow('result', result)
cv2.waitKey()

关于ruby - 即使一张图像的裁剪/比例略有不同,我如何检测到两张图像是 "the same"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60002747/

相关文章:

ruby-on-rails - 简单的 Rails 格式验证未触发

ruby - 如何验证 rspec 中的退出值?

ruby-on-rails - rake 数据库 :reset 'user does not have CONNECT privilege'

python - OpenCV:用轮廓上的大多数点拟合椭圆(而不是最小二乘法)

opencv - 实时光流

algorithm - 如何自动调整颜色和对比度

ruby-on-rails - 将 Gem 'wdm' 添加到您的 GemFile

ios - 需要在 iOS 应用程序中实现用户驱动的裁剪

opencv - 更改图像opencv的宽度步长

python - 如何使用 opencv 从皮肤图像中去除毛发?