我只能找到 C/C++ 中的示例,而且它们似乎从来没有很好地映射到 OpenCV API。我正在加载视频帧(来自文件和网络摄像头),并希望将它们减少到 16 色,但映射到 24 位 RGB 颜色空间(这就是我的输出所需要的 - 一个巨大的 LED 显示屏)。
我读到的数据是这样的:
ret, frame = self._vid.read()
image = cv2.cvtColor(frame, cv2.COLOR_RGB2BGRA)
我确实找到了下面的 python 示例,但无法弄清楚如何将其映射到我需要的输出数据类型:
import numpy as np
import cv2
img = cv2.imread('home.jpg')
Z = img.reshape((-1,3))
# convert to np.float32
Z = np.float32(Z)
# define criteria, number of clusters(K) and apply kmeans()
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K = 8
ret,label,center=cv2.kmeans(Z,K,None,criteria,10,cv2.KMEANS_RANDOM_CENTERS)
# Now convert back into uint8, and make original image
center = np.uint8(center)
res = center[label.flatten()]
res2 = res.reshape((img.shape))
cv2.imshow('res2',res2)
cv2.waitKey(0)
cv2.destroyAllWindows()
这显然适用于 OpenCV 图像查看器,但尝试在我的输出代码上执行相同的错误,因为我需要 RGB 或 RGBA 格式。我的输出是这样的:
for y in range(self.height):
for x in range(self.width):
self._led.set(x,y,tuple(image[y,x][0:3]))
每种颜色都表示为一个 (r,g,b) 元组。
对于如何实现这项工作有什么想法吗?
最佳答案
我认为以下可能比 kmeans 更快,特别是 k = 16 时。
- 将彩色图像转换为灰度
- 对比度拉伸(stretch)此灰度图像,使生成的图像灰度级介于 0 到 255 之间(使用归一化和NORM_MINMAX)
- 使用 16 作为分箱数 (calcHist) 计算此拉伸(stretch)灰度图像的直方图
- 现在您可以修改直方图的这 16 个值。例如,您可以排序和分配排名(例如 0 到 15),或者分配 0 到 255 之间的 16 个均匀分布的值(我认为这些可以为您提供一致的视频输出)
- 将此直方图反投影到拉伸(stretch)的灰色图像上 (calcBackProject)
- 将颜色图应用到该反投影图像(您可能需要在使用 applyColorMap 应用颜色图之前缩放反投影图像)
kmeans 提示: 如果您将 kmeans 用于视频,则可以使用前一帧中的聚类中心作为当前帧的 kmeans 中的初始位置。这样,收敛时间就会更少,因此后续帧中的 kmean 很可能会运行得更快。
关于python - 在 OpenCV Python 中将图像减少为 N 种颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32678992/