查找图像中对象的面积和颜色
Finding the area and colours of an object in an image
我有一张看起来像这样的图片:
我想弄清楚几件事:
- 纹身的主要颜色是什么?
- 皮肤的主要颜色是什么?
- 上面纹身的纹身面积(以像素为单位)是多少?
我是图像处理的新手,但我的攻击计划是这样的:
- 运行边缘检测
- 填充轮廓
- 采用该图像的 alpha 得到纹身的 alpha
width * height * % of white in alpha = area of tattoo ink
- 将 alpha 应用于原始图像并获取颜色分布,以某种方式给出类似 "this tattoo has black and red in it"
的答案
- 反转 alpha 并将其应用于原始图像以获取肤色并找到平均色调
这看起来是获得最终结果的明智方法吗?作为新手,有没有我可能不知道的更简单/更可靠的东西?
我 运行 使用 skimage
对它进行了一些边缘分析代码,得到了这样的轮廓:
但是我在使用颜色填充轮廓以创建 alpha 时遇到了问题。问题是我只想知道 墨水 的面积,而不是整个纹身的面积,所以这似乎更难填充轮廓
我不使用边缘检测和轮廓,而是建议使用以下方法-
1) 将图像从 RGB 转换为灰度。
2) 使用自适应阈值将其转换为二进制图像(我在查看您上传的图像后建议这样做)。
3)现在只要简单的计算像素点的个数,就可以得到纹身和皮肤的面积。
4) 要计算主要颜色(我在这里只看到两种颜色),您可以从二值图像中求出与纹身和皮肤对应的所有像素的平均值,或者您可以计算颜色直方图。
另一种方法是通过 k 均值聚类执行 颜色量化。所提供示例中的纹身只有一种颜色,因此量化后的图像应该有两种颜色,即墨水和皮肤。
import numpy as np
from skimage import io
from sklearn.cluster import KMeans
img = io.imread('https://i.stack.imgur.com/Upcb0.png')
n_colors = 2
X = img.reshape((-1, 3))
kmeans = KMeans(n_clusters=n_colors, random_state=0).fit(X)
labels = kmeans.labels_
centers = kmeans.cluster_centers_
quantized = centers[labels].reshape(img.shape).astype('uint8')
io.imshow(quantized)
主要颜色的 RGB 坐标是:
In [69]: centers
Out[69]:
array([[ 226.44193236, 193.24337359, 175.1311746 ],
[ 40.0549615 , 36.64523871, 40.75754915]])
假设墨水比皮肤深(即墨水颜色的欧几里得范数小于皮肤的欧几里德范数),纹身覆盖的图像像素比例可以这样计算:
In [70]: darkest = np.argmin(np.sqrt(np.sum(centers**2, axis=1)))
In [71]: np.true_divide(np.sum(labels == darkest), labels.size)
Out[71]: 0.24738437499999999
我有一张看起来像这样的图片:
我想弄清楚几件事:
- 纹身的主要颜色是什么?
- 皮肤的主要颜色是什么?
- 上面纹身的纹身面积(以像素为单位)是多少?
我是图像处理的新手,但我的攻击计划是这样的:
- 运行边缘检测
- 填充轮廓
- 采用该图像的 alpha 得到纹身的 alpha
width * height * % of white in alpha = area of tattoo ink
- 将 alpha 应用于原始图像并获取颜色分布,以某种方式给出类似 "this tattoo has black and red in it" 的答案
- 反转 alpha 并将其应用于原始图像以获取肤色并找到平均色调
这看起来是获得最终结果的明智方法吗?作为新手,有没有我可能不知道的更简单/更可靠的东西?
我 运行 使用 skimage
对它进行了一些边缘分析代码,得到了这样的轮廓:
但是我在使用颜色填充轮廓以创建 alpha 时遇到了问题。问题是我只想知道 墨水 的面积,而不是整个纹身的面积,所以这似乎更难填充轮廓
我不使用边缘检测和轮廓,而是建议使用以下方法-
1) 将图像从 RGB 转换为灰度。
2) 使用自适应阈值将其转换为二进制图像(我在查看您上传的图像后建议这样做)。
3)现在只要简单的计算像素点的个数,就可以得到纹身和皮肤的面积。
4) 要计算主要颜色(我在这里只看到两种颜色),您可以从二值图像中求出与纹身和皮肤对应的所有像素的平均值,或者您可以计算颜色直方图。
另一种方法是通过 k 均值聚类执行 颜色量化。所提供示例中的纹身只有一种颜色,因此量化后的图像应该有两种颜色,即墨水和皮肤。
import numpy as np
from skimage import io
from sklearn.cluster import KMeans
img = io.imread('https://i.stack.imgur.com/Upcb0.png')
n_colors = 2
X = img.reshape((-1, 3))
kmeans = KMeans(n_clusters=n_colors, random_state=0).fit(X)
labels = kmeans.labels_
centers = kmeans.cluster_centers_
quantized = centers[labels].reshape(img.shape).astype('uint8')
io.imshow(quantized)
主要颜色的 RGB 坐标是:
In [69]: centers
Out[69]:
array([[ 226.44193236, 193.24337359, 175.1311746 ],
[ 40.0549615 , 36.64523871, 40.75754915]])
假设墨水比皮肤深(即墨水颜色的欧几里得范数小于皮肤的欧几里德范数),纹身覆盖的图像像素比例可以这样计算:
In [70]: darkest = np.argmin(np.sqrt(np.sum(centers**2, axis=1)))
In [71]: np.true_divide(np.sum(labels == darkest), labels.size)
Out[71]: 0.24738437499999999