如何在 Tensorflow.js 中计算拉普拉斯算子?
How do I compute Laplacian in Tensorflow.js?
我目前正在尝试设计一个 Node.js 代码来判断图像是否模糊。为了实现这一目标,我汲取了灵感 from this question。所以我需要做的是计算拉普拉斯矩阵(我们是这么说的吗?)然后计算方差。
我用 OpenCV 没问题(使用 opencv4nodejs):
# load image
_cvImg = cv.imread _file
# get grayscale image
_cvImgGray =_cvImg.bgrToGray()
# Compute laplacian
_laplacian = _cvImgGray.laplacian(cv.CV_8U)
# Get the standard deviation
_meanStdDev = _laplacian.meanStdDev()
_stddevarray = _meanStdDev.stddev.getDataAsArray()
_stdDeviation = _stddevarray[0]
# Get the variation
_variation = Math.pow(_stdDeviation, 2)
但是现在,我正在使用 Tensorflow.js 并且它真的不那么容易......这是我尝试做的:
# load image
_cvImg = cv.imread _file
#convert frame to a tensor
try
_data = new Uint8Array(_frame.cvtColor(cv.COLOR_BGR2RGB).getData().buffer)
_tensorFrame = tfjs.tensor3d(_data, [_frame.rows, _frame.cols, 3])
catch _err
@log.error "Error instantiating tensor !!!"
@log.error _err.message
# get grayscale image
_grayscaleFrame = _tensorFrame.mean(2).expandDims(2)
# prepare convolution to get laplacian
laplaceFilter = tfjs.tensor2d([[0,1,0], [1,-4,1], [0,1,0]])
laplaceFilter3D = laplaceFilter.expandDims(2)
# get laplacian
_laplacian = tfjs.conv1d _tensorFrame, laplaceFilter3D, 1, 'same'
# get standard deviation
_standardDeviation = tfjs.moments(_laplacian2).variance.buffer().values[0]
# get variance
_variance = _standardDeviation * _standardDeviation
# dispose tensor to avoid memeory leaks
_tensorFrame.dispose()
毫不奇怪,上面的代码不起作用。我知道我的卷积应该是二维的 (tf.conv2d) 而不是一维的 (tf.conv1d),因为我正在处理图像。如果我查看 tf.conv2d in API,我可以看到这个签名:
tf.conv2d (x, filter, strides, pad, dataFormat?, dilations?, dimRoundingMode?)
过滤器应该是 tf.Tensor4D !但我不知道如何将以下过滤器矩阵转换为 tf.Tensor4D
1
1 4 1
1
我做错了什么吗?如何在 Tensorflow.js 中获取矩阵的拉普拉斯算子?即如何在代表我的图像的 tensor2d 和上面的过滤器之间执行简单的卷积?
卷积可以通过首先扩展二维张量的维度来执行。同样对于过滤器使用 tf.reshape
计算完成后,tf.squeeze会去掉shape 1的维度,返回一个2d张量
const x = tf.tensor2d(Array.from({length: 16}, (_, k) => k+1), [4, 4]); // input image 2d
const filter = tf.tensor2d([0, 1, 0, 1, 0, 1, 0, 1, 0], [3, 3]) // input filter 2d
x.reshape([1, ...x.shape, 1]).conv2d(filter.reshape([...filter.shape, 1, 1]), 1, 'valid').squeeze().print() // conv
<html>
<head>
<!-- Load TensorFlow.js -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.14.1"> </script>
</head>
<body>
</body>
</html>
另一个解决方案:
// Reads the image, converts to gray and makes shape (1, width, height, 1) [batch, in_height, in_width, in_channels]
let _grayscaleFrame = tf.browser.fromPixels(canvas).mean(2).toFloat().expandDims(0).expandDims(-1);
// prepare convolution to get laplacian
let laplaceFilter = tf.tensor2d([
[0, 1, 0],
[1, -4, 1],
[0, 1, 0]
]).expandDims(-1).expandDims(-1); // [filter_height, filter_width, in_channels, out_channels]
// get laplacian
let _laplacian = _grayscaleFrame.conv2d(laplaceFilter, 1, 'valid').squeeze()
我目前正在尝试设计一个 Node.js 代码来判断图像是否模糊。为了实现这一目标,我汲取了灵感 from this question。所以我需要做的是计算拉普拉斯矩阵(我们是这么说的吗?)然后计算方差。
我用 OpenCV 没问题(使用 opencv4nodejs):
# load image
_cvImg = cv.imread _file
# get grayscale image
_cvImgGray =_cvImg.bgrToGray()
# Compute laplacian
_laplacian = _cvImgGray.laplacian(cv.CV_8U)
# Get the standard deviation
_meanStdDev = _laplacian.meanStdDev()
_stddevarray = _meanStdDev.stddev.getDataAsArray()
_stdDeviation = _stddevarray[0]
# Get the variation
_variation = Math.pow(_stdDeviation, 2)
但是现在,我正在使用 Tensorflow.js 并且它真的不那么容易......这是我尝试做的:
# load image
_cvImg = cv.imread _file
#convert frame to a tensor
try
_data = new Uint8Array(_frame.cvtColor(cv.COLOR_BGR2RGB).getData().buffer)
_tensorFrame = tfjs.tensor3d(_data, [_frame.rows, _frame.cols, 3])
catch _err
@log.error "Error instantiating tensor !!!"
@log.error _err.message
# get grayscale image
_grayscaleFrame = _tensorFrame.mean(2).expandDims(2)
# prepare convolution to get laplacian
laplaceFilter = tfjs.tensor2d([[0,1,0], [1,-4,1], [0,1,0]])
laplaceFilter3D = laplaceFilter.expandDims(2)
# get laplacian
_laplacian = tfjs.conv1d _tensorFrame, laplaceFilter3D, 1, 'same'
# get standard deviation
_standardDeviation = tfjs.moments(_laplacian2).variance.buffer().values[0]
# get variance
_variance = _standardDeviation * _standardDeviation
# dispose tensor to avoid memeory leaks
_tensorFrame.dispose()
毫不奇怪,上面的代码不起作用。我知道我的卷积应该是二维的 (tf.conv2d) 而不是一维的 (tf.conv1d),因为我正在处理图像。如果我查看 tf.conv2d in API,我可以看到这个签名:
tf.conv2d (x, filter, strides, pad, dataFormat?, dilations?, dimRoundingMode?)
过滤器应该是 tf.Tensor4D !但我不知道如何将以下过滤器矩阵转换为 tf.Tensor4D
1
1 4 1
1
我做错了什么吗?如何在 Tensorflow.js 中获取矩阵的拉普拉斯算子?即如何在代表我的图像的 tensor2d 和上面的过滤器之间执行简单的卷积?
卷积可以通过首先扩展二维张量的维度来执行。同样对于过滤器使用 tf.reshape
计算完成后,tf.squeeze会去掉shape 1的维度,返回一个2d张量
const x = tf.tensor2d(Array.from({length: 16}, (_, k) => k+1), [4, 4]); // input image 2d
const filter = tf.tensor2d([0, 1, 0, 1, 0, 1, 0, 1, 0], [3, 3]) // input filter 2d
x.reshape([1, ...x.shape, 1]).conv2d(filter.reshape([...filter.shape, 1, 1]), 1, 'valid').squeeze().print() // conv
<html>
<head>
<!-- Load TensorFlow.js -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@0.14.1"> </script>
</head>
<body>
</body>
</html>
另一个解决方案:
// Reads the image, converts to gray and makes shape (1, width, height, 1) [batch, in_height, in_width, in_channels]
let _grayscaleFrame = tf.browser.fromPixels(canvas).mean(2).toFloat().expandDims(0).expandDims(-1);
// prepare convolution to get laplacian
let laplaceFilter = tf.tensor2d([
[0, 1, 0],
[1, -4, 1],
[0, 1, 0]
]).expandDims(-1).expandDims(-1); // [filter_height, filter_width, in_channels, out_channels]
// get laplacian
let _laplacian = _grayscaleFrame.conv2d(laplaceFilter, 1, 'valid').squeeze()