如何在 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()