基于OpenCV的自动报靶识别实验

基于OpenCV的自动报靶识别实验

问题

户外胸环靶自动报靶问题,目前是通过声电等方式来识别,成本较高,本文尝试使用图像处理的方法来识别。
Alt

方案

前提:固定相机

  1. 确定靶子的四个顶点:目前使用人工手动标注,暂不考虑自动,这步尤为关键直接影响后续弹孔位置确定
  2. 提取靶子:透视变换
  3. 寻找最新的弹孔:a)优先图像处理 + 帧差,需要像素级对齐,b)深度学习检测器,需要收集训练数据,对粘连弹孔检测效果未必理想
  4. 寻找同心圆圆心:椭圆检测方法,https://github.com/memory-overflow/standard-ellipse-detection
  5. 依据圆心与弹孔的距离确定环数

实验

  1. 手动确定靶子四个顶点:
    坐标如下:
const std::vector<cv::Point2f> src_points = {{241,  0}, {417,  2145}, {3325, 0}, {3209, 2157}};
const std::vector<cv::Point2f> dst_points = {{0,   0}, {0,   500}, {500, 0}, {500, 500}};
  1. 提取靶子
    利用opencv提供的透视变换
cv::Mat M = cv::getPerspectiveTransform(src_points, dst_points);
cv::Mat target1, target2;
cv::warpPerspective(img1, target1, M, cv::Size(500, 500));
cv::warpPerspective(img2, target2, M, cv::Size(500, 500));

效果:
Alt

  1. 寻找最新弹孔
    先进行灰度化 -> 进行中值滤波减少噪声干扰 -> 二值化,弹孔明显黑于其它
	// 灰度
    cv::Mat gray1_, gray2_;
    cv::cvtColor(target1, gray1_, cv::COLOR_BGR2GRAY);
    cv::cvtColor(target2, gray2_, cv::COLOR_BGR2GRAY);
    // 中值滤波
    cv::Mat gray1, gray2;
    cv::medianBlur(gray1_, gray1, 5);
    cv::medianBlur(gray2_, gray2, 5);
    // 二值化
    cv::Mat bin1, bin2;
    cv::threshold(gray1, bin1, 90, 255, cv::THRESH_BINARY_INV);
    cv::threshold(gray2, bin2, 90, 255, cv::THRESH_BINARY_INV);

二值化效果:
Alt
帧差结果,仍然有些对齐误差或者图像退化导致的像素差异:

cv::Mat diff = bin2 - bin1;

效果:
Alt
使用中值滤波去除误差影响,图像腐蚀膨胀也可以

    cv::medianBlur(diff, diff, 3); // 中值滤波滤除残差像素

效果:
Alt
寻找弹孔轮廓,计算图像中心矩确定弹孔中心点:

    cv::findContours(diff, contours, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);
    //计算图像矩
    std::vector<cv::Moments> mu(contours.size());
    std::vector<cv::Point2f> mc(contours.size());
    for (int i = 0; i < contours.size(); i++) {
        mu[i] = cv::moments(contours[i], false);
        mc[i] = cv::Point2f(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);
        cv::circle(diff, mc[i], 1, cv::Scalar(0), -1);
    }

效果:
Alt
4. 寻找同心圆圆心:
椭圆检测方法,https://github.com/memory-overflow/standard-ellipse-detection

    std::vector<std::shared_ptr<Ellipse> > ells;
    bool success = detectEllipse(gray1_.data, gray1_.rows, gray1_.cols, ells);
    std::cout << ells.size() << std::endl;
    for (const auto& ell : ells) {
        std::cout << "coverage: " << ell->coverangle << ", goodness: " << ell->goodness << ", polarity: " << ell->polarity << std::endl;
        cv::ellipse(target1,
                cv::Point(ell->o.y, ell->o.x),
                cv::Size(ell->a, ell->b),
                rad2angle(PI_2 - ell->phi),
                0,
                360,
                cv::Scalar(0, 255, 0), 2, 8);

    }

效果:
Alt

结论

虽然可以通过图像处理的方法,确定弹孔和圆心的位置,从而换算出靶数;户外打靶很受环境因素影响,一套参数很难适用全部情况,且提取的同心圆有畸变影响靶数的准确,而且靶子的顶点自动定位是个较大的困难,如果相机视角再是不固定的情况,还得做像素级配准。

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
基于OpenCV的车牌识别实验环境需要安装以下软件和库: 1. Python 3.x:Python是实现车牌识别的主要编程语言之一,可以在官网下载安装包进行安装。 2. OpenCVOpenCV是一个开源的计算机视觉库,主要用于图像处理和计算机视觉应用程序的开发。可以通过pip命令来安装OpenCV: ``` pip install opencv-python ``` 3. Numpy:Numpy是Python中的一个常用数值计算库,用于处理多维数组和矩阵计算。可以通过pip命令来安装Numpy: ``` pip install numpy ``` 4. Tesseract-OCR:Tesseract-OCR是一个开源的OCR库,用于文字识别。可以在官网下载安装包进行安装。 在安装完以上软件和库之后,可以开始进行车牌识别实验。以下是一个基于OpenCV的车牌识别实验的简单代码示例: ```python import cv2 import numpy as np import pytesseract # 读取图像 img = cv2.imread('car.jpg') # 图像预处理 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (5, 5), 0) edges = cv2.Canny(blur, 100, 200) # 查找车牌区域 contours, _ = cv2.findContours(edges.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) contours = sorted(contours, key=cv2.contourArea, reverse=True)[:10] screenCnt = None for c in contours: peri = cv2.arcLength(c, True) approx = cv2.approxPolyDP(c, 0.018 * peri, True) if len(approx) == 4: screenCnt = approx break # 透视变换 if screenCnt is not None: mask = np.zeros(gray.shape, np.uint8) new_image = cv2.drawContours(mask, [screenCnt], 0, 255, -1) new_image = cv2.bitwise_and(img, img, mask=mask) (x, y) = np.where(mask == 255) (topx, topy) = (np.min(x), np.min(y)) (bottomx, bottomy) = (np.max(x), np.max(y)) cropped = gray[topx:bottomx + 1, topy:bottomy + 1] # 车牌识别 text = pytesseract.image_to_string(cropped, config='--psm 11') print("识别结果:", text) cv2.imshow('image', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 以上代码可以实现对车牌区域的查找、透视变换和车牌识别。其中,通过调整Canny算法的参数,可以实现对较为复杂的车牌区域的查找。调整Tesseract-OCR的配置参数,可以提高车牌识别的准确率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值