一 识别场景

二 项目配置 QT mingw+opencv

3 源文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <opencv2/opencv.hpp>
#include <QFileDialog>
#include <vector>
#include <string>
#include <QImage>
using namespace cv;
using namespace std;namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();QImage MatToQImage(Mat MatImg);Mat Oimg;//保存碎片的变量Mat img_src; //保存原始招聘的变量void detection(Mat DstImg,Mat RefImgs);
private slots:void on_pushButton_clicked();void on_pushButton_2_clicked();void on_pushButton_3_clicked();//获取而分化值double GetThreshValOtsu(const cv::Mat& Matsrc);//计算白边圆膜Mat BordStrel(int iRadius);//计算角度double CalLineAngle(vector<vector<Point> > conLeft,vector<Vec4i> hierLeft,vector<vector<Point> > conRight,vector<Vec4i> hierRight,int index);
private:Ui::MainWindow *ui;int m_x,m_y,m_w,m_h; //设置识别区域的变量
};#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
const double PI=3.1415926;MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);m_x = 180;m_y = 150;m_w = 350;m_h = 300;
}MainWindow::~MainWindow()
{delete ui;
}
//图像缓缓转成bgr的图像
QImage MainWindow::MatToQImage(Mat MatImg){Mat cvRgbImg;cvtColor(MatImg, cvRgbImg, CV_BGR2RGB);QImage dstImage((const uchar *)cvRgbImg.data, cvRgbImg.cols, cvRgbImg.rows, cvRgbImg.step, QImage::Format_RGB888);dstImage.bits();return dstImage;
}// Image  添加大图
void MainWindow::on_pushButton_3_clicked() //设置按钮
{QString filename = QFileDialog::getOpenFileName(this,tr("open image"),".",tr("Image Files(*.png)"));img_src = imread(filename.toStdString());//读取图像QImage temp = MatToQImage(img_src);//调用函数,将Mat类型转化为QImage,防止有中文图片无法被识别ui->label_2->setScaledContents(true);ui->label_2->setPixmap(QPixmap::fromImage(temp));
}//Image 添加碎片
void MainWindow::on_pushButton_clicked()
{QString filename = QFileDialog::getOpenFileName(this,tr("open image"),".",tr("Image Files(*.png)"));Oimg = imread(filename.toStdString());QImage temp = MatToQImage(Oimg);//调用函数,将Mat类型转化为QImage,防止有中文图片无法被识别ui->label->setScaledContents(true);//图片自适应label大小ui->label->setPixmap(QPixmap::fromImage(temp));
}void MainWindow::detection(Mat DstImg, Mat RefImgs){Rect rect(m_x, m_y, m_w, m_h);//解读图像的水平值X,Y轴,宽度,高度Mat test = RefImgs.clone();//原图备份DstImg = DstImg(Rect(m_x, m_y, m_w, m_h));RefImgs = RefImgs(Rect(m_x, m_y, m_w, m_h));int height = DstImg.rows;int width = DstImg.cols;Mat rmask = RefImgs.clone();Mat rmask2 = RefImgs.clone();Mat mask= DstImg.clone();Mat mask2 = DstImg.clone();Mat grayDstImg;Mat grayRefImgs;cvtColor(DstImg, grayDstImg, CV_RGB2GRAY);cvtColor(RefImgs, grayRefImgs, CV_RGB2GRAY);double level = GetThreshValOtsu(grayDstImg);Mat bGrayDstImg, bGrayRefImgs;threshold(grayDstImg, bGrayDstImg, level, 255, 0);   // 二值化threshold(grayRefImgs, bGrayRefImgs, level, 255, 0);   // 二值化Mat sel = BordStrel(5);//腐蚀erode(bGrayDstImg, bGrayDstImg, sel);erode(bGrayRefImgs, bGrayRefImgs, sel);vector<vector<Point> >contours1;//定义轮廓。contours就是输出的轮廓。vector<vector<Point> > contours;是一组点的向量。vector<Vec4i> hierarchy1;//hierarchy是描述轮廓信息的信息。vector<Vec4i> hierarchy;每个contours[i]对应hierarchy[i][0]到hierarchy[i][3]这四个值findContours(bGrayDstImg, contours1, hierarchy1, RETR_CCOMP, CHAIN_APPROX_SIMPLE);//查找轮廓//cout << contours1.size() << endl;for (int i = 0; i < contours1.size(); i++) {//绘制每一个轮廓Scalar color(255, 255, 255);drawContours(mask, contours1, i, color, -1, 8, hierarchy1);}int bb = 0, gg = 0, rr = 0, n = 0;for (int row = 0; row < height; row++) {for (int col = 0; col < width; col++) {int b = mask2.at<Vec3b>(row, col)[0];int g = mask2.at<Vec3b>(row, col)[1];int r = mask2.at<Vec3b>(row, col)[2];int mb = mask.at<Vec3b>(row, col)[0];int mg = mask.at<Vec3b>(row, col)[1];int mr = mask.at<Vec3b>(row, col)[2];if (mb == 255) {bb += b; n++;}if (mg == 255) gg += g;if (mr == 255) rr += r;}}bb /= n;gg /= n;rr /= n;cout << bb << " " << gg << " " << rr << endl;//查找绘制轮廓vector<vector<Point> >contours2;vector<Vec4i> hierarchy2;findContours(bGrayRefImgs, contours2, hierarchy2, RETR_CCOMP, CHAIN_APPROX_SIMPLE);for (int i = 0; i < contours2.size(); i++) {Scalar color(255, 255, i);cout << i << endl;//绘制轮廓drawContours(rmask, contours2, i, color, -1, 8, hierarchy2);}vector<vector<Point> >contours3;vector<Vec4i> hierarchy3;dilate(bGrayRefImgs, bGrayRefImgs, sel);  //白线轮廓//查找轮廓findContours(bGrayRefImgs, contours3, hierarchy3, RETR_CCOMP, CHAIN_APPROX_SIMPLE);for (int i = 0; i < contours2.size(); i++) {int tempb = 0, tempg = 0, tempr = 0, tempn = 0; //行rows:Y (height),列cols:X (width)for (int row = 0; row < height; row++) {for (int col = 0; col < width; col++) {int b = rmask2.at<Vec3b>(row, col)[0];int g = rmask2.at<Vec3b>(row, col)[1];int r = rmask2.at<Vec3b>(row, col)[2];int mb = rmask.at<Vec3b>(row, col)[0];int mg = rmask.at<Vec3b>(row, col)[1];int mr = rmask.at<Vec3b>(row, col)[2];//cout << "mr:" << mr << " i:" << i << endl;if (mb == 255&& mr == i) {tempb += b; tempn++;}if (mg == 255&& mr == i) tempg += g;if (mr == i) tempr += r;}}tempb /= tempn;tempg /= tempn;tempr /= tempn;cout << tempb << " " << tempg << " " << tempr << endl;if (abs(tempb - bb) > 20 && abs(tempg - gg) > 20 && abs(tempr - rr) > 20)continue;if (abs(contourArea(contours2[i]) - contourArea(contours1[0])) > 100)continue;//利用矩计算中心点Moments M;M = moments(contours3[i]);int cX = int(M.m10 / M.m00);int cY = int(M.m01 / M.m00);//计算旋转角度  打印信息double angle=CalLineAngle(contours1,hierarchy1,contours3,hierarchy3,i);Scalar color(255, 255, 255);drawContours(test(Rect(m_x, m_y, m_w, m_h)), contours3, i, color, 2, 8, hierarchy3);circle(test(Rect(m_x, m_y, m_w, m_h)), Point2d(cX, cY), 1, Scalar(0, 255, 0), 2, 8);putText(test(Rect(m_x, m_y, m_w, m_h)), "x:"+to_string(cX) , Point2d(cX - 20, cY - 40), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 1, 8);putText(test(Rect(m_x, m_y, m_w, m_h)), "y:"+to_string(cY), Point2d(cX - 20, cY - 20), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 1, 8);putText(test(Rect(m_x, m_y, m_w, m_h)), "Angle:"+to_string(angle), Point2d(cX - 20, cY - 60), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 1, 8);}//清除contours1.clear();contours2.clear();contours3.clear();hierarchy1.clear();hierarchy2.clear();hierarchy3.clear();QImage temp = MattoQImage(test);ui->label->clear();ui->label->setScaledContents(true);ui->label->setPixmap(QPixmap::fromImage(temp));}void MainWindow::on_pushButton_2_clicked()
{detection(img_src,Oimg);
}//获取二值化阈值
double MainWindow::GetThreshValOtsu(const cv::Mat& Matsrc)//二值化,otsu为最大类间方差法,src,source(缩写),指向外部资源的位置,指向的内容将会应用到文档中当前标签所在位置
{cv::Size size = Matsrc.size();if (Matsrc.isContinuous()){size.width *= size.height;size.height = 1;}const int N = 256;int i, j, h[N] = { 0 };for (i = 0; i < size.height; i++){const uchar* src = Matsrc.data + Matsrc.step*i;for (j = 0; j <= size.width - 4; j += 4){int v0 = src[j], v1 = src[j + 1];h[v0]++; h[v1]++;v0 = src[j + 2]; v1 = src[j + 3];h[v0]++; h[v1]++;}for (; j < size.width; j++)h[src[j]]++;}                                      //           平均值double mu = 0, scale = 1. / (size.width*size.height);for (i = 0; i < N; i++)mu += i * h[i];//累加均值mu *= scale;double mu1 = 0, q1 = 0;//q1 ,q2 为类1和类2的概率累积和,mu1=mg*q1double max_sigma = 0, max_val = 0;//循环求取最大阈值//遍历循环for (i = 0; i < N; i++){double p_i, q2, mu2, sigma;p_i = h[i] * scale;//直方图归一化mu1 *= q1;q1 += p_i;q2 = 1. - q1;if (std::min(q1, q2) < FLT_EPSILON || std::max(q1, q2) > 1. - FLT_EPSILON)continue;mu1 = (mu1 + i * p_i) / q1;mu2 = (mu - q1 * mu1) / q2;sigma = q1 * q2*(mu1 - mu2)*(mu1 - mu2);//类间方差if (sigma > max_sigma){max_sigma = sigma;max_val = i;//记下使类间方差最大的阈值}}return max_val;//返回阈值
}//计算白边圆膜
Mat MainWindow::BordStrel(int iRadius)
{Mat sel(2 * iRadius - 1, 2 * iRadius - 1, CV_8UC1, Scalar(1));int borderWidth = 0;switch (iRadius){case 1: borderWidth = 0; break;case 3: borderWidth = 0; break;case 5: borderWidth = 2; break;case 7: borderWidth = 2; break;case 9: borderWidth = 4; break;case 11: borderWidth = 6; break;case 13: borderWidth = 6; break;case 15: borderWidth = 8; break;case 17: borderWidth = 8; break;case 19: borderWidth = 10; break;case 21: borderWidth = 10; break;default: borderWidth = 2; break;}for (int i = 0; i < borderWidth; i++) {for (int j = 0; j < borderWidth - i; j++) {sel.at<uchar>(i, j) = 0;sel.at<uchar>(i, sel.cols - 1 - j) = 0;sel.at<uchar>(sel.rows - 1 - i, j) = 0;sel.at<uchar>(sel.rows - 1 - i, sel.cols - 1 - j) = 0;//创建圆膜方便腐蚀}}return sel;
}//存储计算线角度
double MainWindow::CalLineAngle(vector<vector<Point> > conLeft,vector<Vec4i> hierLeft,vector<vector<Point> > conRight,vector<Vec4i> hierRight,int index){//初始化mat为全黑的图像Mat tempLeft = Mat::zeros(550, 450,CV_8UC1);Mat tempRight= Mat::zeros(550, 450,CV_8UC1);//255有可能需要换成1,代表颜色//将轮廓绘制到mat里,便于后续操作drawContours(tempLeft, conLeft, 0, 255, 2, 8, hierLeft);drawContours(tempRight, conRight, index, 255, 2, 8, hierRight);//定义4个顶点的变量int xLeft1,yLeft1,xLeft2,yLeft2,xLeft3,yLeft3,xLeft4,yLeft4;//找顶点坐标for(int i=0;i< tempLeft.rows;i++){for(int j=0;j< tempLeft.cols;j++){if(tempLeft.at<uchar>(i, j)==255) {xLeft1=i;yLeft1=j;break;}}}//根据顶点数目和顶点位置,找出你要的线,然后就是数学问题和逻辑考虑了double temp=atan2(xLeft1 - xLeft2 , yLeft1 - yLeft2)*180/ PI;return temp;}

qt+opencv进行七巧板识别应用(三)相关推荐

  1. 使用OpenCV进行人脸识别的三种算法(官方网翻译)

    怎样使用OpenCV进行人脸识别 本文大部分来自OpenCV官网上的Face Reconition with OpenCV这节内容(http://docs.opencv.org/modules/con ...

  2. 使用OpenCV进行人脸识别的三种方法

    1 简介 OpenCV从版本2.4开始,加入了一个类FaceRecognizer,使用它可以方便的地进行人脸识别(源代码,在OpenCV的opencv\modules\contrib\doc\face ...

  3. QT OpenCV人脸考勤识别

    前言 突发奇想 要做一个人脸考勤系统 我编译的是最新的OpenCV3.4.17的库 这玩意编译了一晚上 这玩意我也很想写一个 Mingw32 OpenCV的编译 但是这个有可能我没报错的地方你们报错了 ...

  4. win7下配置qt+opencv 注意事项

    根据最近项目需求,需要搞OPENCV,之前有用过MFC,感觉内部使用还是可以的,但是想要弄成可以发布的东东,还是需要比较强大的界面设计的,后来一查,发现QT比较适合,而且还支持跨平台.就风风火火的搞了 ...

  5. 12.QT + OpenCV打包成应用(以及QT图标问题详细) --- OpenCV从零开始到图像(人脸 + 物体)识别系列

    本文作者:小嗷 微信公众号:aoxiaoji 关键词:QT + OpenCV打包成应用(接着第11篇) QT开发的程序发布的时候经常采用两种方式: 静态编译,可生成单一的可执行文件. 动态编译,需同时 ...

  6. 基于qt和opencv实现人脸识别打卡系统

    最近在学习opencv,因此就想着和QT结合起来实现一个人脸识别的系统来.下面我来给大家讲讲这个项目怎么实现的 1.项目源码 https://github.com/SagapoZ/FaceRecogn ...

  7. Qt+OpenCV之图片中的人脸识别及人脸抠图

    效果 OpenCV函数知识点 imread() 功能:载入图像 函数原型:Mat cv::imread ( const String & filename, int flags = IMREA ...

  8. Qt 使用摄像头通过openCV进行人脸识别

    Qt 使用摄像头通过openCV进行人脸识别 资源下载 环境信息 1. 下载cpenCV和opencv_contrib源码 2. 安装CMake 3. 编译openCV 开始编译 4. 新建工程调用o ...

  9. 【OpenCV+Qt】使用车牌识别系统EasyPR识别车牌号

    EasyPR是一个中文的开源车牌识别系统,其车牌识别划分为了两个过程:即车牌检测(Plate Detection)和字符识别(Chars Recognition)两个过程: 车牌检测(Plate De ...

最新文章

  1. python的知识点注意事项
  2. 如何构建一个成功的AI PoC(概念验证项目)
  3. “比特币耶稣”Roger Ver:比特币现金分叉没有技术论据支持
  4. 精通python设计模式-浅谈Python设计模式 - 原型模式
  5. 【Linux网络编程】原始套接字实例:发送 UDP 数据包
  6. python scrapy框架爬虫_Scrapy爬虫框架教程(一)-- Scrapy入门
  7. 如何在Safari中查看网页的完整URL
  8. runas/cpau/lsrunase使用小结(以管理员运行指定程序)
  9. java 多个数字_java 输入多个数字
  10. python生成json_python中如何进行json转化
  11. 在Windows上安装虚拟机详细图文教程
  12. 老司机用CATIA的实用默认值更改
  13. 像素密度(衡量屏幕显示能力)
  14. JS逆向-易班登录password参数(RSA加密)
  15. 如何重启Windows资源管理器
  16. 【信号处理】基于Matlab实现男女音变声系统
  17. mysql 分区表如何恢复_如何恢复mysql 单个innodb 分区表
  18. 电力系统系统潮流分析【IEEE 57 节点】(Matlab代码实现)
  19. uniapp禁止单页面侧滑返回
  20. sed命令定义和常用方式

热门文章

  1. 教师资格证 中学科目二 简答/辨析/材料 知识点与口诀
  2. matlab跳动的心脏,Matlab绘制跳动的心
  3. 使用PHPExcel类库编写一个快捷的导出函数
  4. 日常(别吐槽了TwT人都傻了)
  5. 笔记:Spring基础
  6. Xftp 传文件到虚拟机一直显示状态错误,传不进去
  7. 汇编指令:MRS(读)和MSR(写)指令操作CPSR寄存器和SPSR寄存器使用
  8. 学习笔记(17):零基础掌握 Python 入门到实战-重复利用,事半功倍
  9. mediautil.jar java操作jpg信息,添加水印
  10. 【IT情感】久坐易死,IT人员您知道吗