opencv 风挡轮廓补全

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

        项目需要识别出汽车车前窗部分,通过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)
H,
  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值