0黑色,1白色

static inline cv::Mat find_road(cv::Mat& frame)
{
    // 获取一个2x2的十字形结构元素
    cv::Mat kernel = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(2, 2));
    // 对二值化后的帧进行开运算,去除噪声
    cv::morphologyEx(binarizedFrame, morphologyExFrame, cv::MORPH_OPEN, kernel);

    // 创建一个全零的掩膜,大小为行跟踪高度+2,列跟踪宽度+2
    cv::Mat mask = cv::Mat::zeros(line_tracking_height + 2, line_tracking_width + 2, CV_8UC1);

    // 设置种子点,位于行跟踪宽度的中间,行跟踪高度的倒数第二行
    cv::Point seedPoint(line_tracking_width / 2, line_tracking_height - 10);

    // 在开运算后的帧中绘制一个半径为10的白色圆
    cv::circle(morphologyExFrame, seedPoint, 10, 255, -1);

    // 设置填充颜色为128
    cv::Scalar newVal(128);

    // 设置上下差异为20
    cv::Scalar loDiff = cv::Scalar(20);
    cv::Scalar upDiff = cv::Scalar(20);

    // 对开运算后的帧进行泛洪填充,填充颜色为128,上下差异为20
    cv::floodFill(morphologyExFrame, mask, seedPoint, newVal, 0, loDiff, upDiff, 8);

    // 创建一个全零的输出图像,大小为行跟踪宽度,行跟踪高度
    cv::Mat outputImage = cv::Mat::zeros(line_tracking_width, line_tracking_height, CV_8UC1);

    // 将掩膜中的图像复制到输出图像中
    mask(cv::Rect(1, 1, line_tracking_width, line_tracking_height)).copyTo(outputImage);

    // 返回输出图像
    return outputImage;
}

# 1. 结构元素创建

cv::Mat kernel = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(2, 2));
  • 功能:创建2x2的十字形结构元素
  • 为什么用:十字形结构能有效处理线状结构(如道路标线),小尺寸(2x2)适合去除微小噪声
  • 效果:为后续形态学操作准备基础核

# 2. 开运算去噪

cv::morphologyEx(binarizedFrame, morphologyExFrame, cv::MORPH_OPEN, kernel);
  • 功能:对二值图像执行开运算(先腐蚀后膨胀)
  • 为什么用
    • 消除细小噪声点(如路面碎石、图像噪点)
    • 保持道路主体结构完整(十字核能更好保留线状特征)
  • 效果:获得更干净的道路二值图像

# 3. 掩膜初始化

cv::Mat mask = cv::Mat::zeros(line_tracking_height + 2, line_tracking_width + 2, CV_8UC1);
  • 功能:创建比原图大2像素的掩膜
  • 为什么+2:OpenCV的floodFill要求掩膜尺寸必须为(width+2) x (height+2)
  • 效果:为泛洪填充提供符合规范的存储空间

# 4. 种子点设置

cv::Point seedPoint(line_tracking_width / 2, line_tracking_height - 10);
  • 功能:在图像底部中间位置设置种子点
  • 为什么用
    • 假设车辆通常位于道路中央(宽度中点)
    • 距底部10像素:避开图像边缘,确保在道路区域内
  • 效果:为区域生长确定起始位置

# 5. 绘制种子区域

cv::circle(morphologyExFrame, seedPoint, 10, 255, -1);
  • 功能:以种子点为中心画半径为10的实心白圆
  • 为什么用
    • 确保种子区域足够大(避免落在小孔洞/裂缝中)
    • 强制连接可能断裂的道路区域
  • 效果:创建可靠的泛洪填充起始区域

# 6. 泛洪填充参数

cv::Scalar newVal(128);       // 填充值
cv::Scalar loDiff(20), upDiff(20); // 容差
  • 参数意义
    • newVal=128:填充灰度值(中等灰色)
    • loDiff/upDiff=20:允许的像素值浮动范围
  • 为什么用20:在二值图像中,20的容差能覆盖从深灰(235)到纯白(255)的渐变

# 7. 执行泛洪填充

cv::floodFill(morphologyExFrame, mask, seedPoint, newVal, 0, loDiff, upDiff, 8);
  • 功能:从种子点开始区域生长
  • 参数解析
    • 8:使用8连通域(考虑对角线方向)
    • 0:无标志位(默认行为)
  • 效果:将道路连通区域标记为128(掩膜中对应区域变为1)

# 8. 提取道路掩膜

cv::Mat outputImage = cv::Mat::zeros(line_tracking_width, line_tracking_height, CV_8UC1);
mask(cv::Rect(1, 1, line_tracking_width, line_tracking_height)).copyTo(outputImage);
  • 功能:从大掩膜中裁剪有效区域
  • Rect(1,1,...):去除floodFill添加的边界
  • 效果:获得与原图同尺寸的道路二值掩膜(道路=1,背景=0)