我正在尝试使用模型对灰度图像进行分类。
我使用了一些TensorflowJS示例中提供的extension type来使用网络摄像头获取图像。它运行良好,但它返回RGB图像。
将此图像转换为灰度的最佳方法是什么?我是否需要计算这个从张量中获取每个元素并计算一个代表灰度图像的新矩阵,还是有更简单或方便的方法?
答案 0 :(得分:1)
表示图像的3D张量具有以下形状:(高度,宽度,number_of_channels)。因此,RGB图像具有形状(高度,宽度,3)。
要转换为灰度,我使用最后一个轴(number_of_channels轴)计算平均值。因此,每个像素值现在是R,G和B值的平均值。
grayscale_image = image.mean(2)
此操作删除张量的最后一个维度,返回一个形状(高度,宽度)的张量。
为了保持形状(高度,宽度,number_of_channels),我扩展了尺寸:
final_image = grayscale_image.expandDims(2)
final_image的形状(高度,宽度,1)
答案 1 :(得分:1)
要将图像转换为灰度,应删除深度通道尺寸或将其减小为一。
给出张量t,这是两种处理方法
tensor.mean(2)
tensor.slice([0, 0, 0], [a.shape[0], a.shape[1], 1])
tf.toPixels显示来自张量的图像。
3-移调频道(HWC-> CHW)
通过转置通道,由于toPixel也可以与2D张量一起使用,因此可以将2D基础图像以阵列的形式堆叠起来
const c = a.transpose([2, 0, 1]).unstack()[0];
const im = new Image()
im.crossOrigin = "anonymous";
im.src = "https://i.imgur.com/lVlPvCB.gif"
document.body.appendChild(im)
im.onload = () => {
const a = tf.fromPixels(im, 4)
const canvas = document.createElement('canvas');
const canvas1 = document.createElement('canvas');
const canvas2 = document.createElement('canvas');
tf.toPixels(a.mean(2).div(255.0), canvas);
const b = a.slice([0, 0, 0], [a.shape[0], a.shape[1], 1])
tf.toPixels(b, canvas1);
const c = a.transpose([2, 0, 1]).unstack()[0];
tf.toPixels(c, canvas2);
document.body.append(canvas);
document.body.append(canvas1);
document.body.append(canvas2);
}
<html>
<head>
<!-- Load TensorFlow.js -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.14.1/dist/tf.min.js"> </script>
</head>
<body>
</body>
</html>
答案 2 :(得分:1)
从RGB图像获取灰度的首选方法是根据ITU-R建议(BT.601)。 Matlab,OpenCV和Tensorflow(python)都是这样做的。
灰色= 0.2989 * R + 0.5870 * G + 0.1140 * B
如果是这样,我想到的最好方法是举一个简单的示例,该示例应扩展为任意大小的图像:
// make an image that is size 2x2, with 3 color channels
x = tf.randomUniform([2, 2, 3]);
// print out the tensor so you know what you started with
x.print();
// the scalars needed for conversion of each channel
// per the formula: gray = 0.2989 * R + 0.5870 * G + 0.1140 * B
rFactor = tf.scalar(0.2989);
gFactor = tf.scalar(0.5870);
bFactor = tf.scalar(0.1140);
// separate out each channel. x.shape[0] and x.shape[1] will give you
// the correct dimensions regardless of image size
r = x.slice([0,0,0], [x.shape[0], x.shape[1], 1]);
g = x.slice([0,0,1], [x.shape[0], x.shape[1], 1]);
b = x.slice([0,0,2], [x.shape[0], x.shape[1], 1]);
// add all the tensors together, as they should all be the same dimensions.
gray = r.mul(rFactor).add(g.mul(gFactor)).add(b.mul(bFactor));
// check your work
gray.print();
答案 3 :(得分:0)
对我而言唯一有效的解决方案是首先对RGB通道值求平均,然后使用tf.stack复制平均值,并再次使图像形状适合RGB。
一个例子:
// load a tensor from a canvas image
let t = await tf.fromPixels(canvas, 3);
// at this point shape should be [width, height, 3]
// now average along the channel dimension to get average of RGB for each pixel
t = t.mean(2);
// at this point shape should be [width, height]
// finally, repeat each monochrome value three times to get our shape back to RGB
t = tf.stack([t, t, t], 2);
// final shape is again [width, height, 3]
答案 4 :(得分:0)
如果您需要采用[宽度,高度,1]形式:
tf.browser.fromPixels(image)
.mean(2)
.toFloat()
.expandDims(-1)
如果您需要[1,width,height,1]形式:
tf.browser.fromPixels(image)
.mean(2)
.toFloat()
.expandDims(0)
.expandDims(-1)