基于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 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();
}