基于OpenCV的条形码区域分割
要基于OpenCV实现条形码区域分割,可以按照以下步骤进行:
- 加载图像:使用OpenCV中的imread函数读取待处理图像。
- 灰度化:使用OpenCV中的cvtColor函数将彩色图像转换为灰度图像。
- 边缘检测:使用OpenCV中的Canny函数对灰度图像进行边缘检测,得到二值图像。
- 轮廓检测:使用OpenCV中的findContours函数对二值图像进行轮廓检测,得到所有轮廓的列表。
- 轮廓筛选:遍历所有轮廓,使用OpenCV中的boundingRect函数计算每个轮廓的包围矩形,并根据矩形的宽高比和面积进行筛选,得到符合条件的条形码区域。
- 绘制矩形:使用OpenCV中的rectangle函数在原图上绘制符合条件的条形码区域。
- 显示图像:使用OpenCV中的imshow函数显示处理后的图像。
但是由于选取的图片比较复杂,这样的常规流程是识别不出效果的,所以在原有的流程上又添加了新的处理:
- 黑帽算法:使用黑帽算法可以将杂色有效去除。黑帽是一种常用的图像处理算法,可以用于图像增强、边缘检测、形态学变换等应用。
- 二值化:通过黑帽算法设定合适的阈值来将图像有用部分提取出来。
- 膨胀+闭运算:将图像连接起来
- 开运算:将不符合的区间去除
效果:
代码:
#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 RGBQImage 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();
}