opencv 风挡轮廓补全

本文介绍了如何使用OpenCV、Python和K-means解决汽车风挡轮廓不完整的问题。首先通过K-means聚类区分边线,接着用四阶多项式拟合曲线并进行修补裁剪,最终实现车窗完整轮廓的提取。虽然传统方法对光照条件敏感,但对于某些情况仍能提供良好效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        工作中遇到了一个问题,好不容易解决了,写个博客了记录一下。

        项目需要识别出汽车车前窗部分,通过ROI选取出来,再进行下一步的处理。我利用一些办法得到了如图1所示的轮廓,但是效果很不好。图中可见车窗四个边只有左侧、右侧和下侧轮廓,各个轮廓很不连续,断线问题很严重,并且这张图片已经是数据集里效果比较好的,还有更多的图片轮廓断线更为严重,直接提取ROI非常困难。

图1. 原始车窗识别效果

        因为实验室光线的问题,轮廓的断线基本无法避免,利用传统CV算法补全很麻烦,而且不一定能适应所有的情况,我准备先用传统算法实现,然后下一步再利用深度学习的方法找出来车窗。想要真的适应更多的情况确实还是得用深度学习,后续我再写一篇分享一下,目前先分享我的传统CV解决方案。

        我的思路是先把所有的点按边分类,分类完成后在对这些点进行拟合,然后对拟合的曲线进行修补和裁剪,防止轮廓出现凹陷的地方,最后再画一下轮廓就完成了。先把所有用到的包加载一下,sklearn用来拟合和分类,numba用来快速找两个多维数组的差异,其他的就是很常规的包。

import cv2
import numpy as np
import numba as nb
import copy as cp
from sklearn import linear_model
from sklearn.cluster import KMeans
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.metrics import mean_squared_error as MSE

        单独写出来的函数如下所示,

    MSE_Singel

        用来计算MSE,用于进一步分类所有的点。

    setdiff2d_nb

        这个函数用来寻找两个二维数组中的差异元素,运算速度非常快。


def MSE_Singel(y_pred, y):
    return (y_pred-y)**2

def temp_imshow(size, idx):
    class_left = np.full(size, 255)
    class_left[list(idx[0]), list(idx[1])] = 0
    class_left = class_left.astype(np.uint8)
    cv2.namedWindow('left', 0)
    cv2.imshow('left', class_left)
    cv2.waitKey(0)

@nb.njit
def mul_xor_hash(arr, init=65537, k=37):
    result = init
    for x in arr.view(np.uint64):
        result = (result * k) ^ x
    return result

@nb.njit
def setdiff2d_nb(arr1, arr2):
    # : build `delta` set using hashes
    delta = {mul_xor_hash(arr2[0])}
    for i in range(1, arr2.shape[0]):
        delta.add(mul_xor_hash(arr2[i]))
    # : compute the size of the result
    n = 0
    for i in range(arr1.shape[0]):
        if mul_xor_hash(arr1[i]) not in delta:
            n += 1
    # : build the result
    result = np.empty((n, arr1.shape[-1]), dtype=arr1.dtype)
    j = 0
    for i in range(arr1.shape[0]):
        if mul_xor_hash(arr1[i]) not in delta:
            result[j] = arr1[i]
            j += 1
    return result

        首先需要导入图片,二值化处理一下。需要补全的四个边最好处理的就是左右两个,因为基本就是直线。我用了K-means来聚类,为了剔除上下两边的影响,先把图片切成了cut_top,cut_middle,cut_bottom三块,中间块就只有左右两条边,因此用中间块来聚类。

image = cv2.imread('base_pic1.jpg')
image_gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
retVal, image_thresh = cv2.threshold(image_gray, 150, 255, cv2.THRESH_BINARY)
cv2.namedWindow('1', 0)
cv2.imshow('1', image_thresh)
cv2.waitKey(0)
#聚类
#1.照片三分类或者二分类,上半张图聚两类
image_cut = cp.copy(image_thresh)
### OpenCV 轮廓补全的解决方案 在图像处理领域,轮廓补全通常涉及边缘检测、掩模生成以及修复算法的应用。以下是一个基于 OpenCV轮廓补全方法的完整示例,结合了 Canny 边缘检测、`findContours` 函数和图像修复技术。 #### 1. 使用 Canny 算法进行边缘检测 Canny 算法是一种经典的边缘检测方法,能够有效提取图像中的轮廓信息[^1]。以下是使用 Canny 算法的代码示例: ```python import cv2 import numpy as np # 读取图像 image = cv2.imread('input_image.jpg', cv2.IMREAD_GRAYSCALE)[^2] # 应用高斯模糊以减少噪声 blurred = cv2.GaussianBlur(image, (5, 5), 0) # 使用 Canny 算法检测边缘 edges = cv2.Canny(blurred, threshold1=50, threshold2=150) ``` #### 2. 提取轮廓并生成掩模 通过 `findContours` 函数可以提取图像中的轮廓,并将其转换为掩模图像[^1]。以下是具体实现: ```python # 查找轮廓 contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 创建一个空白掩模 mask = np.zeros_like(image) # 绘制轮廓到掩模上 cv2.drawContours(mask, contours, -1, (255), thickness=cv2.FILLED) ``` #### 3. 使用图像修复算法进行轮廓补全 OpenCV 提供了两种主要的图像修复算法:`INPAINT_NS` 和 `INPAINT_TELEA`[^3]。以下是如何应用这些算法进行轮廓补全的示例: ```python # 读取原始彩色图像 color_image = cv2.imread('input_image.jpg') # 应用图像修复 restored_ns = cv2.inpaint(color_image, mask, 3, cv2.INPAINT_NS) restored_telea = cv2.inpaint(color_image, mask, 3, cv2.INPAINT_TELEA) # 显示结果 cv2.imshow('Original Image', color_image) cv2.imshow('Restored (NS)', restored_ns) cv2.imshow('Restored (TELEA)', restored_telea) cv2.waitKey(0) cv2.destroyAllWindows() ``` #### 4. 结果分析 上述方法通过 Canny 边缘检测提取轮廓,利用 `findContours` 和 `drawContours` 生成掩模,最后通过图像修复算法完成轮廓补全。需要注意的是,修复效果可能因输入图像的质量和参数选择而有所不同[^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值