python - RGB 图像的像素强度以及如何将其与整数相乘以查看灰度阴影
问题描述
我有一个 RGB 图像,它有 4 种不同的颜色黑色(0,0,0)作为背景,绿色(106,136,93)蓝色(64,224,208)和棕色(168,124,85)。当我将图像读取为灰度并使用 np.unique() 它返回一个巨大的像素强度列表。但实际上,只有 4 种强度,即 [0,1,2,3] 黑色、绿色、蓝色和棕色。
import cv2
import numpy as np
test = cv2.imread("test-BlackBG.png",0) #test image
results = np.unique(test) #returns [0,1,2,3,4,5,6,7,8...........132]
print(test.shape) #returns (480, 640)
print(results)
cv2.imshow("image",test)
cv2.waitKey()
cv2.destroyAllWindows()
预期结果:当我将图像乘以 85 时,它应该以不同的灰度显示所有 3 种强度。
解决方案
您的问题和假设存在许多问题。
你不能数颜色np.unique(image)
您无法用 计算图像中的颜色np.unique(im)
。让我们看看为什么制作一个只有 4 个强度的随机图像:0、1、2 和 3。
import numpy as np
import cv2
# Ensure repeatable, deterministic randomness!
np.random.seed(42)
# Make a random image
im = np.random.randint(0,4,(480,640,3), dtype=np.uint8)
看起来像这样,其中每一行是一个像素的 RGB 三元组:
array([[[2, 2, 3],
[3, 2, 1],
[2, 2, 0],
...,
[3, 3, 2],
[0, 0, 1],
[1, 1, 1]],
...,
[3, 3, 1],
[2, 3, 0],
[0, 1, 3]]], dtype=uint8)
现在,如果您尝试获得这样的独特颜色,它将无法正常工作,因为每种颜色都是3 种强度的组合:
np.unique(im) # prints: array([0, 1, 2, 3], dtype=uint8)
然而,如果您想要唯一颜色的数量,则需要查找三个 RGB/BGR 值的唯一组合的数量:
np.unique(im.reshape(-1, im.shape[2]), axis=0)
它给出了图像中唯一 RGB/BGR 三元组的向量 - 每行都是唯一的颜色组合:
array([[0, 0, 0],
[0, 0, 1],
[0, 0, 2],
[0, 0, 3],
[0, 1, 0],
[0, 1, 1],
[0, 1, 2],
[0, 1, 3],
[0, 2, 0],
[0, 2, 1],
[0, 2, 2],
[0, 2, 3],
[0, 3, 0],
[0, 3, 1],
[0, 3, 2],
[0, 3, 3],
[1, 0, 0],
[1, 0, 1],
[1, 0, 2],
[1, 0, 3],
[1, 1, 0],
[1, 1, 1],
[1, 1, 2],
[1, 1, 3],
[1, 2, 0],
[1, 2, 1],
[1, 2, 2],
[1, 2, 3],
[1, 3, 0],
[1, 3, 1],
[1, 3, 2],
[1, 3, 3],
[2, 0, 0],
[2, 0, 1],
[2, 0, 2],
[2, 0, 3],
[2, 1, 0],
[2, 1, 1],
[2, 1, 2],
[2, 1, 3],
[2, 2, 0],
[2, 2, 1],
[2, 2, 2],
[2, 2, 3],
[2, 3, 0],
[2, 3, 1],
[2, 3, 2],
[2, 3, 3],
[3, 0, 0],
[3, 0, 1],
[3, 0, 2],
[3, 0, 3],
[3, 1, 0],
[3, 1, 1],
[3, 1, 2],
[3, 1, 3],
[3, 2, 0],
[3, 2, 1],
[3, 2, 2],
[3, 2, 3],
[3, 3, 0],
[3, 3, 1],
[3, 3, 2],
[3, 3, 3]], dtype=uint8)
或者,作为一组简单的独特颜色:
len(np.unique(im.reshape(-1, im.shape[2]), axis=0)) # prints 64
因此,对于您的图像:
# Open image
im = cv2.imread('image.png',cv2.IMREAD_UNCHANGED)
# Count unique colours
len(np.unique(im.reshape(-1, im.shape[2]), axis=0) # prints 790
颜色比你想象的要多
为什么我的颜色比我预期的要多?最常见的两个原因是:
- 图像被保存为 JPEG
- 有抗锯齿的文本或绘制的形状
让我们看看另存为 JPEG 是如何搞砸你的!
# Load image and count colours
im = cv2.imread('image.png',cv2.IMREAD_UNCHANGED)
len(np.unique(im.reshape(-1, im.shape[2]), axis=0)) # prints 790
# Save as JPEG
cv2.imwrite('temp.jpg',im)
# Reload and recount just the same
im = cv2.imread('temp.jpg',cv2.IMREAD_UNCHANGED)
len(np.unique(im.reshape(-1, im.shape[2]), axis=0)) # prints 4666 !!!
如何对图像进行调色 - (将颜色减少到固定调色板)?
如果您想将图像调色到您自己的特定调色板,首先您需要以 BGR 顺序 ( !
) 指定您的调色板以匹配 OpenCV 的顺序:
palette = np.array([
[0,0,0], # Black
[93,136,106], # Green
[208,224,64], # Blue
[85,124,168]], # Brown
dtype=np.uint8)
然后阅读您的图像,丢弃完全无意义的 alpha 通道:
test = cv2.imread("image.png",cv2.IMREAD_COLOR)
然后计算从每个像素到每个调色板条目的距离:
distance = np.linalg.norm(test[:,:,None] - palette[None,None,:], axis=3)
然后为每个像素选择最接近的调色板颜色:
palettised = np.argmin(distance, axis=2).astype(np.uint8)
您的图像现在位于数组中palettised
,并且存储在每个像素位置是调色板中最近颜色的索引 - 因此,由于您的调色板有 4 个条目 (0..3),因此图像的所有元素都是 0、1、2或 3。
所以,现在你可以乘以 85:
result = palettised * 85
推荐阅读
- python - 将 tf.Dataset 拆分为测试和验证子集的规范方法是什么?
- php - 爆炸,推动一个元素并在一个动作中内爆
- django - 有没有办法改变 django 中的添加表列?
- c++ - 以缺少 const 作为参数的纯虚函数的重新定义
- android - 如何在 Android Enterprise Work Profile 中调试应用程序
- visual-studio - 通过命令提示符为 Visual Studio 部署项目创建构建
- mysql - 为什么同一查询会得到不同的输出?
- java - 安全地从 Spring 后面反应前面。安全不允许查看主页
- angular - Angular 8如何根据所选材料选项卡更改材料日期选择器的提供者?
- angular - Excel导出将日期时间视为数字