Hap*_*yPy 2 python similarity euclidean-distance
我有两个相同大小的 rgb 图像,我想计算一个相似性度量。我想从欧几里得距离开始:
import scipy.spatial.distance as dist
import cv2
im1 = cv2.imread("im1.jpg")
im2 = cv2.imread("im2.jpg")
>> im1.shape
(820, 740, 3)
>> dist.euclidean(im1,im2)
ValueError: Input vector should be 1-D.
Run Code Online (Sandbox Code Playgroud)
我知道dist.euclidean需要一个1-d阵列和im1和im2是3-d,但有将与3-d阵列工作,或者是否有可能变换函数im1和im2到1-d阵列蜜饯在图像中的信息?
在我看来,您可以使用灰度图像而不是 RGB 图像来解决问题。我知道我在这里做假设,但这是一个想法。
我将尝试一个与您的代码相关的简单示例,然后给出一个使用 2D 离散傅立叶变换的图像相似性度量示例,该变换使用灰度转换。DFT 分析将有自己的部分
(如果你在进行中看到这个,我很抱歉。我只是想确保我的工作得到保存。)
由于我的假设,我将用一些 RGB 图像尝试您的方法,然后看看是否可以通过转换为灰度来解决问题。如果问题是用灰度解决的,我们可以通过使用所有三个通道的组合找到图像相似性来分析灰度解决方案带来的信息损失量,每个通道分别进行比较。
方法
确保我拥有所有的库/包/任何你想称呼它们的东西。
> python -m pip install opencv-python
> python -m pip install scipy
> python -m pip install numpy
Run Code Online (Sandbox Code Playgroud)
请注意,在本次试用中,我使用了一些在尝试(如下所述)中创建的 PNG 图像来使用 2D DFT。
确保我遇到同样的问题
> python -m pip install opencv-python
> python -m pip install scipy
> python -m pip install numpy
Run Code Online (Sandbox Code Playgroud)
现在,让我们尝试使用灰度。如果这可行,我们可以简单地找到每个 RGB 通道的距离。我希望它有效,因为我想做信息丢失分析。
让我们转换为灰度:
>>> import scipy.spatial.distance as dist
>>> import cv2
>>>
>>> im1 = cv2.imread("rhino1_clean.png")
>>> im2 = cv2.imread("rhino1_streak.png")
>>>
>>> im1.shape
(178, 284, 3)
>>>
>>> dist.euclidean(im1, im2)
## Some traceback stuff ##
ValueError: Input vector should be 1-D.
Run Code Online (Sandbox Code Playgroud)
一个简单的dist.euclidean(im1_gray, im2,gray)会导致同样的ValueError: Input vector should be 1-D.异常,但我知道灰度图像数组(像素行数组)的结构,所以我做了以下操作。
>>> im1_gray = cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)
>>> im2_gray = cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)
>>> im1_gray.shape
(178, 284)
Run Code Online (Sandbox Code Playgroud)
顺便说一下,这是两张原始图片:
灰度有效(带按摩),让我们试试颜色
按照this SO answer中的一些程序,让我们执行以下操作。
继这里的分析(存档),让我们看看我们的信息丢失。(请注意,这将是一个非常幼稚的分析,但我想对其进行破解。
灰度与颜色信息
让我们看看颜色与灰度。稍后,我们可以查看是否保留了有关距离的信息。
使用灰度与所有三个通道的不同距离度量的比较 - 使用一组图像的距离总和的比率进行比较。
我不知道如何对距离进行熵测量,但我的直觉告诉我,如果我使用灰度和颜色通道计算距离,如果我没有丢失任何信息,我应该得出类似的距离比率。
看到这个问题时,我的第一个想法是使用 2-D 离散傅立叶变换,我确信它在 Python、NumPy 或 OpenCV 中可用。基本上,DFT 的第一个组件将与图像中的大形状相关。(这是我将在此处放入相关研究论文的地方:link。我没有仔细看 - 欢迎任何人提出另一个建议。)
因此,让我查找可从 Python 轻松获得的 2-D DFT,然后我将返回来提交一些工作代码。
(如果你在进行中看到这个,我很抱歉。我只是想确保我的工作得到保存。)
首先,您需要确保您拥有和。看起来你有,但这里有一些说明。(请注意,我目前在 Windows 上)...PILPillowNumPyNumPy
> python -m pip install opencv-python
> python -m pip install numpy
> python -m pip install pillow
Run Code Online (Sandbox Code Playgroud)
现在,这里有 5 张图片 -
rhino1_clean.jpg(来源);我在 MS Paint 中绘制的带有一些黑色条纹的相同图像rhino1_streak.jpg;
另一个犀牛图像,rhino2_clean.jpg(来源);
第一张河马图像hippo1_clean.jpg(来源);
第二张河马图像,hippo2_clean.jpg(来源)。
合理使用的所有图像。
好的,现在,为了进一步说明,让我们转到 Python 交互式终端。
>python
>>> dists = []
>>> for i in range(0, len(im1_gray)):
... dists.append(dist.euclidean(im1_gray[i], im2_gray[i]))
...
>>> sum_dists = sum(dists)
>>> ave_dist = sum_dists/len(dists)
>>> ave_dist
2185.9891304058297
Run Code Online (Sandbox Code Playgroud)
首先,如果我们使用灰度 PNG 图像,生活会更轻松 - PNG 因为它是直位图(而不是压缩图像),灰度因为我不必用通道显示所有细节。
> python -m pip install opencv-python
> python -m pip install numpy
> python -m pip install pillow
Run Code Online (Sandbox Code Playgroud)
对其他四个图像执行类似的步骤。我使用了 PIL 变量名,rh_img_1_stk, rh_img_2_cln, hp_img_1_cln, hp_img_2_cln。我最终得到了以下灰度图像的图像文件名,我将进一步使用它们:rhino1_streak_gs.png, rhino2_clean_gs.png, hippo1_clean_gs.png, hippo2_clean_gs.png.
现在,让我们获得 DFT 的系数。以下代码(参考此 SO 答案)将用于第一个干净的犀牛图像。
让我们先“看”一下图像数组。这将向我们显示左上列的网格版本,较高的值更白,较低的值更黑。
请注意,在我开始输出这个数组之前,我将其设置为numpy默认值,参见。https://docs.scipy.org/doc/numpy/reference/generated/numpy.set_printoptions.html
>>> import PIL
>>> import numpy as np
Run Code Online (Sandbox Code Playgroud)
>>> rh_img_1_cln = PIL.Image.open("rhino1_clean.jpg")
>>> rh_img_1_cln.save("rhino1_clean.png")
>>> rh_img_1_cln_gs = PIL.Image.open("rhino1_clean.png").convert('LA')
>>> rh_img_1_cln_gs.save("rhino1_clean_gs.png")
Run Code Online (Sandbox Code Playgroud)
现在,让我们运行 DFT 并查看结果。numpy在开始实际转换之前,我更改了打印选项以使事情变得更好。
>>> np.set_printoptions(edgeitems=3,infstr='inf',
... linewidth=75, nanstr='nan', precision=8,
... suppress=False, threshold=1000, formatter=None)
Run Code Online (Sandbox Code Playgroud)
现在,遵循相同程序的结果 rhino1_streak.jpg
>>> rh1_cln_gs_array = np.array(rh_img_1_cln_gs)
>>> for i in {0,1,2,3,4}:
... print(rh1_cln_gs_array[i][:13])
...
[93 89 78 87 68 74 58 51 73 96 90 75 86]
[85 93 64 64 76 49 19 52 65 76 86 81 76]
[107 87 71 62 54 31 32 49 51 55 81 87 69]
[112 93 94 72 57 45 58 48 39 49 76 86 76]
[ 87 103 90 65 88 61 44 57 34 55 70 80 92]
Run Code Online (Sandbox Code Playgroud)
我将打印 \Delta 值而不是做更全面的距离。如果需要距离,可以对此处显示的值的平方求和。
>>> np.set_printoptions(formatter={'all':lambda x: '{0:.2f}'.format(x)})
>>>
>>> rh1_cln_gs_fft = np.fft.fft2(rh_img_1_cln_gs)
>>> rh1_cln_gs_scaled_fft = 255.0 * rh1_cln_gs_fft / rh1_cln_gs_fft.max()
>>> rh1_cln_gs_real_fft = np.absolute(rh1_cln_gs_scaled_fft)
>>> for i in {0,1,2,3,4}:
... print(rh1_cln_gs_real_fft[i][:13])
...
[255.00 1.46 7.55 4.23 4.53 0.67 2.14 2.30 1.68 0.77 1.14 0.28 0.19]
[38.85 5.33 3.07 1.20 0.71 5.85 2.44 3.04 1.18 1.68 1.69 0.88 1.30]
[29.63 3.95 1.89 1.41 3.65 2.97 1.46 2.92 1.91 3.03 0.88 0.23 0.86]
[21.28 2.17 2.27 3.43 2.49 2.21 1.90 2.33 0.65 2.15 0.72 0.62 1.13]
[18.36 2.91 1.98 1.19 1.20 0.54 0.68 0.71 1.25 1.48 1.04 1.58 1.01]
Run Code Online (Sandbox Code Playgroud)
我将仅将三个系数数组截断为长度为 5,以展示其如何用于显示图像相似性。老实说,这对我来说是一个实验,所以我们会看看它是如何进行的。
您可以将这些系数与距离或其他指标进行比较。
让我们用上面提出的方法对信息丢失进行信息理论分析。继这里的分析(存档),让我们看看我们的信息丢失。
祝你好运!