from skimage.metrics import structural_similarity
import cv2
import numpy as np
first = cv2.imread('clownfish_1.jpeg')
second = cv2.imread('clownfish_2.jpeg')
# Convert images to grayscale
first_gray = cv2.cvtColor(first, cv2.COLOR_BGR2GRAY)
second_gray = cv2.cvtColor(second, cv2.COLOR_BGR2GRAY)
# Compute SSIM between two images
score, diff = structural_similarity(first_gray, second_gray, full=True)
print("Similarity Score: {:.3f}%".format(score * 100))
# The diff image contains the actual image differences between the two images
# and is represented as a floating point data type so we must convert the array
# to 8-bit unsigned integers in the range [0,255] before we can use it with OpenCV
diff = (diff * 255).astype("uint8")
# Threshold the difference image, followed by finding contours to
# obtain the regions that differ between the two images
thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
# Highlight differences
mask = np.zeros(first.shape, dtype='uint8')
filled = second.copy()
for c in contours:
area = cv2.contourArea(c)
if area > 100:
x,y,w,h = cv2.boundingRect(c)
cv2.rectangle(first, (x, y), (x + w, y + h), (36,255,12), 2)
cv2.rectangle(second, (x, y), (x + w, y + h), (36,255,12), 2)
cv2.drawContours(mask, [c], 0, (0,255,0), -1)
cv2.drawContours(filled, [c], 0, (0,255,0), -1)
cv2.imshow('first', first)
cv2.imshow('second', second)
cv2.imshow('diff', diff)
cv2.imshow('mask', mask)
cv2.imshow('filled', filled)
cv2.waitKey()
from sentence_transformers import SentenceTransformer, util
from PIL import Image
import glob
import os
# Load the OpenAI CLIP Model
print('Loading CLIP Model...')
model = SentenceTransformer('clip-ViT-B-32')
# Next we compute the embeddings
# To encode an image, you can use the following code:
# from PIL import Image
# encoded_image = model.encode(Image.open(filepath))
image_names = list(glob.glob('./*.jpg'))
print("Images:", len(image_names))
encoded_image = model.encode([Image.open(filepath) for filepath in image_names], batch_size=128, convert_to_tensor=True, show_progress_bar=True)
# Now we run the clustering algorithm. This function compares images aganist
# all other images and returns a list with the pairs that have the highest
# cosine similarity score
processed_images = util.paraphrase_mining_embeddings(encoded_image)
NUM_SIMILAR_IMAGES = 10
# =================
# DUPLICATES
# =================
print('Finding duplicate images...')
# Filter list for duplicates. Results are triplets (score, image_id1, image_id2) and is scorted in decreasing order
# A duplicate image will have a score of 1.00
# It may be 0.9999 due to lossy image compression (.jpg)
duplicates = [image for image in processed_images if image[0] >= 0.999]
# Output the top X duplicate images
for score, image_id1, image_id2 in duplicates[0:NUM_SIMILAR_IMAGES]:
print("\nScore: {:.3f}%".format(score * 100))
print(image_names[image_id1])
print(image_names[image_id2])
# =================
# NEAR DUPLICATES
# =================
print('Finding near duplicate images...')
# Use a threshold parameter to identify two images as similar. By setting the threshold lower,
# you will get larger clusters which have less similar images in it. Threshold 0 - 1.00
# A threshold of 1.00 means the two images are exactly the same. Since we are finding near
# duplicate images, we can set it at 0.99 or any number 0 < X < 1.00.
threshold = 0.99
near_duplicates = [image for image in processed_images if image[0] < threshold]
for score, image_id1, image_id2 in near_duplicates[0:NUM_SIMILAR_IMAGES]:
print("\nScore: {:.3f}%".format(score * 100))
print(image_names[image_id1])
print(image_names[image_id2])
// Compare two images by getting the L2 error (square-root of sum of squared error).
double getSimilarity( const Mat A, const Mat B ) {
if ( A.rows > 0 && A.rows == B.rows && A.cols > 0 && A.cols == B.cols ) {
// Calculate the L2 relative error between images.
double errorL2 = norm( A, B, CV_L2 );
// Convert to a reasonable scale, since L2 error is summed across all pixels of the image.
double similarity = errorL2 / (double)( A.rows * A.cols );
return similarity;
}
else {
//Images have a different size
return 100000000.0; // Return a bad value
}
6条答案
按热度按时间wecizke31#
这是一个庞大的主题,答案从3行代码到整个研究杂志。
我将概述最常见的此类技术及其结果。
比较直方图
最简单、最快的方法之一。几十年前提出的一种寻找图片相似性的方法。其思想是森林会有很多绿色,而人脸会有很多粉红色,或者其他什么。所以,如果你比较两张森林图片,你会得到直方图之间的一些相似性,因为你在两张图片中都有很多绿色。
缺点:它太简单了。香蕉和海滩看起来是一样的,因为都是黄色的。
OpenCV方法:比较历史记录()
模板匹配
matchTemplate finding good match是一个很好的例子。它将搜索图像与要搜索的图像进行卷积。它通常用于在较大的图像中查找较小的图像部分。
缺点:它只返回相同的图像,相同的大小和方向的好结果。
OpenCV方法:匹配模板()
特征匹配
被认为是进行图像搜索的最有效方法之一。从图像中提取多个特征,以保证即使在旋转、缩放或倾斜时也能再次识别相同的特征。用这种方法提取的特征可以与其他图像特征集进行匹配。具有高比例特征与第一个特征匹配的另一个图像被认为描述了相同的场景。
找到两组点之间的单应性还可以让您找到原始图片之间拍摄Angular 的相对差异或重叠量。
有很多OpenCV教程/示例,还有一个不错的视频here,整个OpenCV模块(features 2d)都是专门针对它的。
缺点:它可能很慢。它不完美。
在OpenCV问答网站上,我谈到了特征描述符和纹理描述符之间的区别,特征描述符在比较整个图像时非常重要,纹理描述符用于识别图像中的人脸或汽车等对象。
bz4sfanl2#
由于没有人贴出完整的具体例子,这里有两种定量的方法来确定两幅图像之间的相似度:一种方法是比较维度相同的图像;另一种用于缩放不变和变换无关的图像。这两种方法都返回
0
与100
之间的相似性得分,其中0
表示完全不同的图像,100
表示相同/重复的图像。对于介于两者之间的所有其他值:分数越低,相似性越低;分数越高,越相似。为了比较差异并确定两个图像之间的确切差异,我们可以利用 * 结构相似性指数 * SSIM是一种图像质量评价方法,它基于参考图像和失真图像之间局部信息的统计特性来估计结构相似性的退化,SSIM值的范围在[-1,1],通常使用滑动窗口计算,其中整个图像的SSIM值计算为所有单个窗口结果的平均值。此方法已在scikit-image图像处理库中实现,可随
pip install scikit-image
安装。skimage.metrics.structural_similarity()
函数返回比较结果score
和差值图像,diff
。score
表示两张图像之间的平均SSIM分数,值越高表示相似性越高。diff
图像包含实际图像差异,较暗区域具有更多差异。较大的差异区域以黑色突出显示,而较小的差异以灰色突出显示。此处'这是一个例子:输入图像
差异图像
->
突出显示的蒙片差异比较两幅图像后的SSIM评分显示它们非常相似。
相似度评分:八十九点四六二
为了可视化两幅图像之间的确切差异,我们可以迭代每个轮廓,使用最小阈值区域过滤以去除微小的噪声,并使用边界框突出显示差异。
代码:
通常情况下,两个图像不会完全相同。它们可能会因背景、尺寸、要素添加/减少或变换而略有不同换句话说,我们不能使用直接的像素到像素的方法,因为随着变化,问题从识别像素相似性转移到物体相似性。我们必须转换到深度-学习特征模型而不是比较各个像素值。
为了确定相同和近似的图像,我们可以使用
sentence-transformers
库,它提供了一种简单的方法来计算图像的密集矢量表示,以及OpenAI Contrastive Language-Image Pre-Training (CLIP) Model,它是一个已经在各种(图像,文本)对上训练过的神经网络。其思想是将所有图像编码到矢量空间中,然后找到高密度区域,对应于图像非常相似的区域。比较两幅图像时,会给它们一个
0
到1.00
之间的分数。我们可以使用一个阈值参数来识别两幅图像是相似还是不同。较低的阈值会导致其中具有较少相似图像的聚类。相反,较高的阈值将产生具有更多相似图像的聚类。复制图像将具有1.00
的分数,这意味着两个图像完全相同。为了找到接近相似的图像,我们可以将阈值设置为任意值,例如0.9
,例如,如果两个图像之间确定的得分大于0.9
,则我们可以断定它们是接近相似的图像。举个例子:
这个数据集有五张图像,注意花#1是如何重复的,而其他的是不同的。
花#1及其副本相同
我们在不同的图像之间得到了更有趣的结果,得分越高,相似度越高;分数越低,相似性越低,使用阈值
0.9
或90%,我们可以过滤掉接近相似的图像。第一个计算机7d1x第一个计算机8d1x第一个计算机3b1x第一个计算机9d1x第一个计算机10d1x第一个计算机4b1x第一个计算机11d1x第一个计算机12d1x第一个计算机5b1x第一个计算机13d1x第一个计算机14d1x第一个计算机6b1x
代码:
cnh2zyt33#
如果用于匹配相同图像(相同尺寸/方向)
Source
hzbexzde4#
Sam的解决方案应该足够了。我使用了直方图差异和模板匹配的组合,因为没有一种方法是100%适合我的。虽然我对直方图方法不太重视。下面是我如何在简单的python脚本中实现的。
s4n0splo5#
有点离题但很有用的是Python
numpy
方法,它健壮而快速,但只是比较像素,而不是图片中包含的对象或数据(它需要大小和形状相同的图像):一个非常简单快速的方法是在没有openCV和任何计算机视觉库的情况下,通过以下公式对图片阵列进行归一化:
在定义了两个赋范图(或矩阵)之后,你可以对你想要比较的图的乘积求和:
1)如果你比较相似的图片,总和将返回1:
2)如果它们不相似,则会得到一个介于0和1之间的值(乘以100时为一个百分比):
请注意,如果你有彩色的图片,你必须在所有的三维或只是比较灰度版本。我经常要比较大量的图片与任意的内容,这是一个非常快的方式这样做。
7fyelxc56#
可以对预训练的ImageRes数据使用诸如VGG 16的架构来使用自动编码器用于这样的任务;然后计算查询和其他图像之间的距离,以找到最接近的匹配。