基于OpenCV的条形码区域分割
要基于OpenCV实现条形码区域分割,可以按照以下步骤进行:

  • 加载图像:使用OpenCV中的imread函数读取待处理图像。
  • 灰度化:使用OpenCV中的cvtColor函数将彩色图像转换为灰度图像。
  • 边缘检测:使用OpenCV中的Canny函数对灰度图像进行边缘检测,得到二值图像。
  • 轮廓检测:使用OpenCV中的findContours函数对二值图像进行轮廓检测,得到所有轮廓的列表。
  • 轮廓筛选:遍历所有轮廓,使用OpenCV中的boundingRect函数计算每个轮廓的包围矩形,并根据矩形的宽高比和面积进行筛选,得到符合条件的条形码区域。
  • 绘制矩形:使用OpenCV中的rectangle函数在原图上绘制符合条件的条形码区域。
  • 显示图像:使用OpenCV中的imshow函数显示处理后的图像。

但是由于选取的图片比较复杂,这样的常规流程是识别不出效果的,所以在原有的流程上又添加了新的处理:

  • 黑帽算法:使用黑帽算法可以将杂色有效去除。黑帽是一种常用的图像处理算法,可以用于图像增强、边缘检测、形态学变换等应用。
  • 二值化:通过黑帽算法设定合适的阈值来将图像有用部分提取出来。
  • 膨胀+闭运算:将图像连接起来
  • 开运算:将不符合的区间去除

效果:
opencv_04条形码区域分割-LMLPHP
代码:


#include <QFileDialog>
#include <opencv2/opencv.hpp>
#include <opencv2/saliency/saliencySpecializedClasses.hpp>
#include <opencv2/opencv.hpp>
#include <QApplication>
#include <QFileDialog>
#include <QLabel>
void MainWindow::on_openButton_clicked() {
    QString filename = QFileDialog::getOpenFileName(this, tr("Open Image"), ".", tr("Image Files (*.png *.jpg *.bmp)"));
    if (filename.isEmpty()) {
        return;
    }

    Mat image = imread(filename.toStdString());
    if (image.empty()) {
        return;
    }

    // 灰度化
    Mat grayImage;
    cvtColor(image, grayImage, COLOR_BGR2GRAY);

    // 黑帽 黑帽是一种常用的图像处理算法,可以用于图像增强、边缘检测、形态学变换等应用。
    Mat black_img = blackhat(grayImage, 5);

    // 二值化
    Mat binaryImg;
    threshold(black_img, binaryImg, 80, 255, cv::THRESH_BINARY);

    // 膨胀+闭运算
    Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(10, 5));
    Mat dilated;
    dilate(binaryImg, dilated, kernel);
    Mat closed;
    morphologyEx(dilated, closed, cv::MORPH_CLOSE, kernel);

    // 开运算
    Mat outputImage;
    Mat kernel1 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(20, 20));
    morphologyEx(closed, outputImage, cv::MORPH_OPEN, kernel1);
    imshow("binary image", outputImage);
    // 边缘检测
    Mat edges;
    Canny(outputImage, edges, 50, 150);    // 轮廓检测
    std::vector<std::vector<cv::Point>> contours;
    findContours(edges, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);    // 轮廓筛选
    std::vector<cv::Rect> barcodeRects;
    for (int i = 0; i < contours.size(); i++)    {        // 计算包围矩形
        Rect rect = boundingRect(contours[i]);        // 根据宽高比和面积筛选
        double aspectRatio = static_cast<double>(rect.width) / rect.height;
        if (aspectRatio > 2 && aspectRatio < 4 && rect.area() > 1000) {
            barcodeRects.push_back(rect);
        }
    }
    // 绘制矩形
    for (int i = 0; i < barcodeRects.size(); i++)    {
        rectangle(image, barcodeRects[i], Scalar(255, 255, 0), 2);
    }

    cvtColor(image, image, COLOR_BGR2RGB);//BGR convert to RGB
    QImage qimage(image.data, image.cols, image.rows, image.step, QImage::Format_RGB888);
    ui->label->setPixmap(QPixmap::fromImage(qimage));
    ui->label->resize(qimage.size());
    ui->label->show();
}

04-28 11:51