python opencv 4.1.0 cv2.convertScaleAbs()函数 (通过线性变换将数据转换成8位[uint8])(用于Intel Realsense D435显示depth图像)

API文档

def convertScaleAbs(src, dst=None, alpha=None, beta=None): # real signature unknown; restored from __doc__
    """
    convertScaleAbs(src[, dst[, alpha[, beta]]]) -> dst
    .   @brief Scales, calculates absolute values, and converts the result to 8-bit.
    	缩放,计算绝对值,然后将结果转换为8位。
    .   
    .   On each element of the input array, the function convertScaleAbs
    .   performs three operations sequentially: scaling, taking an absolute
    .   value, conversion to an unsigned 8-bit type:
    	在输入数组的每个元素上,函数convertScaleAbs依次执行三个操作:缩放,获取绝对值,转换为无符号的8位类型:
    	
    .   \f[\texttt{dst} (I)= \texttt{saturate\_cast<uchar>} (| \texttt{src} (I)* \texttt{alpha} +  \texttt{beta} |)\f]
    
    .   In case of multi-channel arrays, the function processes each channel
    .   independently. When the output is not 8-bit, the operation can be
    .   emulated by calling the Mat::convertTo method (or by using matrix
    .   expressions) and then by calculating an absolute value of the result.
		如果是多通道阵列,该函数将独立处理每个通道。 
		当输出不是8位时,可以通过调用Mat :: convertTo方法(或使用矩阵表达式),
		然后通过计算结果的绝对值来模拟该操作。
		
    .   For example:
    .   @code{.cpp}
    .   Mat_<float> A(30,30);
    .   randu(A, Scalar(-100), Scalar(100));
    .   Mat_<float> B = A*5 + 3;
    .   B = abs(B);
    .   // Mat_<float> B = abs(A*5+3) will also do the job,
    .   // but it will allocate a temporary matrix
    .   @endcode
    .   @param src input array. 输入数组。
    .   @param dst output array. 输出数组。
    .   @param alpha optional scale factor. 可选比例因子。
    .   @param beta optional delta added to the scaled values. 可选增量添加到缩放值。
    .   @sa  Mat::convertTo, cv::abs(const Mat&)
    """
    pass

代码示例:Intel Realsense图像的两种对齐方式

cv.convertScaleAbs(depth_image, alpha=0.03)

假设我们需要让我们的深度摄像头感兴趣的距离范围有差别地显示,那么我们就需要确定一个合适的alpha值,公式为:有效距离*alpha=255,假设我们想让深度摄像头8m距离内的深度被显示,>8m的与8m的颜色显示相同,那么alpha=255/(8*10^3)≈0.03,假设我们想让深度摄像头6m距离内的深度被显示,>6m的与6m的颜色显示相同,那么alpha=255/(6*10^3)≈0.0425cv.convertScaleAbs()函数对输入数组进行如下运算:
在这里插入图片描述
对于输入深度图数组中的每个值srci(它是16位的,数据类型是uint16),先乘以系数α,再加上偏置β,最后将结果取绝对值,并截取为8位(uint8),然后返回与原数组相同维度的数组dsti。

验证猜想

猜测如果计算后的值大于255,则将其取为255(8位最大值)。

import numpy as np
import cv2 as cv
depth_image=np.array([[1000,2,3],[8000,-8000,6],[-1000,8,9]])
print('depth_image:\n',depth_image)
depth_image_map=cv.convertScaleAbs(depth_image,alpha=0.03,beta=100)
print('depth_image_map:\n',depth_image_map)

结果:

depth_image:
 [[ 1000     2     3]
 [ 8000 -8000     6]
 [-1000     8     9]]
depth_image_map:
 [[130 100 100]
 [255 140 100]
 [ 70 100 100]]

验证结果正确!

完整示例代码

import pyrealsense2 as rs
import cv2 as cv
import numpy as np

pipeline = rs.pipeline()

cfg = rs.config()
cfg.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)
cfg.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)

# 设定需要对齐的方式(这里是深度对齐彩色,彩色图不变,深度图变换)
align_to = rs.stream.color
# 设定需要对齐的方式(这里是彩色对齐深度,深度图不变,彩色图变换)
# align_to = rs.stream.depth

alignedFs = rs.align(align_to)

profile = pipeline.start(cfg)

try:
    while True:
        fs = pipeline.wait_for_frames()
        aligned_frames = alignedFs.process(fs)

        color_frame = aligned_frames.get_color_frame()
        depth_frame = aligned_frames.get_depth_frame()

        if not depth_frame or not color_frame:
            continue

        color_image = np.asanyarray(color_frame.get_data())
        depth_image = np.asanyarray(depth_frame.get_data())

        # D·C 191122:打印depth_image的最大值看看
        # print(depth_image.max())
        # 可以看到,最大的数值从一万到六万不等(表示最远距离十多米到六十米这样)

        # D·C 191122:打印数据类型看看
        # print(depth_image.dtype)
        # uint16
        # print(color_image.dtype)
        # uint8

        # D·C 191122:打印color_image的维度看看
        # print(color_image.shape)
        # (480, 640, 3)
        # print(depth_image.shape)
        # (480, 640)

        # D·C 191122:打印cv.convertScaleAbs(depth_image, alpha=0.03)的数据类型和维度看看:
        # print(cv.convertScaleAbs(depth_image, alpha=0.03).dtype)
        # uint8
        # print(cv.convertScaleAbs(depth_image, alpha=0.03).shape)
        # (480, 640)

        # D·C 191122:打印cv.applyColorMap(cv.convertScaleAbs(depth_image, alpha=0.03), cv.COLORMAP_JET)的数据类型和维度看看
        # print(cv.applyColorMap(cv.convertScaleAbs(depth_image, alpha=0.03), cv.COLORMAP_JET).dtype)
        # uint8
        # print(cv.applyColorMap(cv.convertScaleAbs(depth_image, alpha=0.03), cv.COLORMAP_JET).shape)
        # (480, 640, 3)

        # D·C 191122:打印cv.convertScaleAbs(depth_image, alpha=0.03)的最大值看看
        # print(cv.convertScaleAbs(depth_image, alpha=0.03))
        # 可看到最大值为255
        # 估计若原值*alpha大于255,则将其取值为255,而当alpha为0.03时,能够映射的最大可变距离为255/0.03=8500mm=8.5m

        # D·C 191122:修改alpha参数后,发现图像对比度发生变化(比如alpha=1,图像基本呈红没啥对比度、alpha=0.001,图像呈蓝也没啥对比度、alpha=1点几,效果也不行)
        # origin:depth_image = cv.applyColorMap(cv.convertScaleAbs(depth_image, alpha=0.03), cv.COLORMAP_JET)
        depth_image = cv.applyColorMap(cv.convertScaleAbs(depth_image, alpha=0.03), cv.COLORMAP_JET)

        images = np.hstack((color_image, depth_image))

        # window = cv.namedWindow('window', cv.WINDOW_AUTOSIZE)

        cv.imshow('window', images)

        cv.waitKey(1)
finally:
    pipeline.stop()

参考文章1:【OpenCV3】cv::convertScaleAbs()使用详解

参考文章2:opencv中图像基础(大小,深度,通道)

参考文章3:图像位深度 8位 16位 24位 32位区别对比 RGB 真彩色 基本概念:(大小,深度,通道)位深度数据类型转换原理 Mat数据读取(opencv里的imread)

  • 22
    点赞
  • 93
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dontla

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值