利用基于深度的图像分割方法从深度图像中分割目标物体的基本步骤如下:
1、获取图像的深度信息。使用Kinect,立体相机或结构光扫描仪获得深度图像,其中每个像素对应一个深度值。
2、分析目标物体的深度分布范围,需要根据目标物体的特征尺寸和相机参数估计其可能的深度区间,作为分割的参考。
3、设定深度阈值,选择一个或多个深度范围。根据上一步的分析结果选择可能包含目标物体的深度区间作为阈值。
4、对深度图像进行二值化。使用设定的深度阈值对深度图像进行二值化,得到可能属于目标物体的前景区域(1)和背景区域(0)
5、通过连接域分析提取目标区域。在二值图像上进行连接域分析,根据像素的连接关系将属于同一目标物体的像素聚合在一起。每个连接域对应一个分割的目标区域。
6、根据需要进行形态学运算。可以对分割结果进行开运算、闭运算等来改善目标边界、填充空洞和去除小区域。
7、利用目标区域的深度信息生成三维点云。根据目标区域内每个像素的图像位置和深度值计算其在三维空间的坐标,构建目标物体的三维模型
8、根据应用要求选择感兴趣的目标物体。

python实现
该实现的主要步骤为:

  1. 读取深度图像并分析目标深度范围,设定深度阈值。
  2. 利用深度阈值对图像进行二值化,得到可能属于目标的前景区域。
  3. 通过连接域分析对二值图像进行分割,得到多个区域。
  4. 根据面积过滤掉较小的区域,保留可能的目标区域。
  5. 根据目标区域生成二值掩膜图像。
  6. 根据目标区域的深度信息计算三维坐标点构建点云。
import cv2
import numpy as np

# 读取深度图像
depth_img = cv2.imread('depth.png', -1)  

# 分析目标深度范围,设定深度阈值
lower_thresh = 200
upper_thresh = 255

# 二值化深度图像 
binary_mask = np.logical_and(depth_img >= lower_thresh, depth_img <= upper_thresh)

# 连接域分析
labels = measure.label(binary_mask, connectivity=2) 
props = measure.regionprops(labels)

# 过滤小区域
target_label = []
for prop in props:
    if prop.area > 1000: 
        target_label.append(prop.label)

# 生成mask        
target_mask = np.isin(labels, target_label) 

# 显示结果
cv2.imshow('Input',depth_img)       
cv2.imshow('Target Mask',target_mask*255)
cv2.waitKey(0) 

# 构建三维点云
points = []
for y in range(depth_img.shape[0]):
    for x in range(depth_img.shape[1]):
        if target_mask[y][x] == 1:
            Z = depth_img[y][x] 
            X = (x - depth_img.shape[1]/2) * Z / fx + Xc
            Y = (y - depth_img.shape[0]/2) * Z / fy + Yc                
            points.append([X, Y, Z])

C++实现
该实现主要步骤与python基本相同

  1. 读取深度图像并分析目标深度范围,设定深度阈值。
  2. 利用深度阈值对图像进行二值化,得到可能属于目标的前景区域。
  3. 通过connectedComponentsWithStats函数实现连接域分析分割,得到多个区域。
  4. 根据面积过滤较小区域,保留可能的目标区域。
  5. 根据目标区域生成二值掩膜图像。
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>

using namespace cv;
using namespace std;

int main() 
{
    // 读取深度图像
    Mat depth_img = imread("depth.png", -1);  

    // 分析目标深度范围,设定深度阈值
    int lower_thresh = 200;
    int upper_thresh = 255;

    // 二值化深度图像 
    Mat binary_mask;
    threshold(depth_img, binary_mask, lower_thresh, upper_thresh, THRESH_BINARY); 

    // 连接域分析
    Mat labels;
    int nlabels = connectedComponentsWithStats(binary_mask, labels, 
        CV_32S, 8, CV_32S); 
   
    // 过滤小区域
    vector<int> target_label;
    for (int i = 1; i < nlabels; i++) 
    {
        Mat stats = connectedComponentsWithStats(binary_mask, labels, 
            CV_32S, 8, CV_32S)[3];
        if (stats.ptr<float>(i)[4] > 1000) target_label.push_back(i);
    }
    
    // 生成mask
    Mat target_mask = Mat::zeros(depth_img.size(), CV_8U);
    for (int y = 0; y < depth_img.rows; y++) 
    {
        for (int x = 0; x < depth_img.cols; x++) 
        {
            if (find(target_label.begin(), target_label.end(),
                labels.ptr<int>(y)[x]) != target_label.end()) 
            {
                target_mask.ptr<uchar>(y)[x] = 255;     
            }
        }
    } 

    // 显示结果
    imshow("Input", depth_img);       
    imshow("Target Mask", target_mask);
    waitKey(0);
 }
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐