TensorFlow中方形核形态学图像膨胀的高效实现方案
TensorFlow方形核形态学图像膨胀效率优化问题
我正在寻求在TensorFlow中实现带方形核的形态学图像膨胀的高效方法。经测试,常规实现方式与OpenCV的实现相比效率极低,测试环境为搭载M1芯片的MacBook Air,测试结果显示即便当前最快的TensorFlow实现,速度也比OpenCV慢约30倍。
对640x480分辨率图像使用25x25核做膨胀操作耗时: 0.61ms 使用opencv实现 545.40ms 使用tf.nn.max_pool2d实现 228.66ms 使用原生tf.nn.dilation2d实现 17.63ms 使用行列分解的tf.nn.dilation2d实现
问题
是否有人知晓在TensorFlow中实现图像膨胀且不存在严重效率缺陷的方法?
现有方案源码
import numpy as np import cv2 import tensorflow as tf import time def tf_dilate(heatmap, width: int, method: str = 'rowcol'): """ Dilate the heatmap with a square kernel """ if method=='maxpool': return tf.nn.max_pool2d(heatmap[None, :, :, None], ksize=width, padding='SAME', strides=(1, 1))[0, :, :, 0] elif method == 'naive_dilate': return tf.nn.dilation2d(heatmap[None, :, :, None], filters=tf.zeros((width, width, 1), dtype=heatmap.dtype), strides=(1, 1, 1, 1), padding="SAME", data_format="NHWC", dilations=(1, 1, 1, 1))[0, :, :, 0] elif method == 'rowcol_dilate': row_dilation = tf.nn.dilation2d(heatmap[None, :, :, None], filters=tf.zeros((1, width, 1), dtype=heatmap.dtype), strides=(1, 1, 1, 1), padding="SAME", data_format="NHWC", dilations=(1, 1, 1, 1)) full_dilation = tf.nn.dilation2d(row_dilation, filters=tf.zeros((width, 1, 1), dtype=heatmap.dtype), strides=(1, 1, 1, 1), padding="SAME", data_format="NHWC", dilations=(1, 1, 1, 1)) return full_dilation[0, :, :, 0] else: raise NotImplementedError(f'No method {method}') def test_dilation_options(img_shape=(480, 640), kernel_size=25): img = np.random.randn(*img_shape).astype(np.float32)**2 def get_result_and_time(version: str): tf_image = tf.constant(img, dtype=tf.float32) t_start = time.time() if version=='opencv': result = cv2.dilate(img, kernel=np.ones((kernel_size, kernel_size), dtype=np.float32)) return time.time()-t_start, result else: result = tf_dilate(tf_image, width=kernel_size, method=version) return time.time()-t_start, result.numpy() t_opencv, result_opencv = get_result_and_time('opencv') t_maxpool, result_maxpool = get_result_and_time('maxpool') t_naive_dilate, result_naive_dilate = get_result_and_time('naive_dilate') t_rowcol_dilate, result_rowcol_dilate = get_result_and_time('rowcol_dilate') assert np.array_equal(result_opencv, result_maxpool), "Maxpool result did not match opencv result" assert np.array_equal(result_opencv, result_naive_dilate), "Naive dilation result did not match opencv result" assert np.array_equal(result_opencv, result_rowcol_dilate), "Row-col dilation result did not match opencv result" print(f'Dilation of {img_shape[1]}x{img_shape[0]} image with a {kernel_size}x{kernel_size} kernel took: ' f'\n {t_opencv*1000:.2f}ms using opencv' f'\n {t_maxpool*1000:.2f}ms using tf.nn.max_pool2d' f'\n {t_naive_dilate*1000:.2f}ms using tf.nn.dilation2d naively' f'\n {t_rowcol_dilate*1000:.2f}ms using tf.nn.dilation2d with row-col' ) if __name__ == '__main__': test_dilation_options()
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

