opencv 图像识别程序
来源:互联网 发布:应知故乡事的前一句 编辑:程序博客网 时间:2024/05/17 01:35
1.头文件
#pragma once#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <iostream>using namespace std;using namespace cv;enum DiColor{RED = 0,BLUE = 1};class ZhuangJia{public: ZhuangJia(); //二值化 void erZhiHua(const Mat &src, Mat &dst, uchar yz); //亮度调整 void liangDuTiaoZheng(const Mat &src, Mat &dst, double k, double b); //寻找目标区域 vector<RotatedRect> xunZhaoJuXing(const Mat &img); //拟合可能区域 vector<RotatedRect> niHeMuBiao(vector<RotatedRect> vr); //寻找最佳目标区域 RotatedRect xunZhaoZuiJia(vector<RotatedRect> vr); //画出目标区域 void huaChuMuBiao(Mat img, RotatedRect vr); //计算距离,返回值越大,距离越大 int jiSuanjuLi(const Mat &imgroi, int &yuzhi);public: uchar huiDu; uchar diColor;//地方颜色标志 int juLiYuZhi; int imgwidth; int imgheight; int liangDu; int jianCeBianChang; Mat erZhiTu; Mat imgG;//绿色通道图像 Mat imgD;//敌方颜色通道图像 Mat imgTemplate; Mat imgTemplateSmall; bool isFar;};
2.源文件
#include "zhuangjia.hpp"#ifndef DEBUG//#define DEBUG#endifZhuangJia::ZhuangJia(){ huiDu = 210; diColor = RED; imgwidth = 640; imgheight = 480; juLiYuZhi = 15; jianCeBianChang = 2; isFar = false; //读取模板图片 Mat img = imread("template.bmp"); vector<Mat> vimg; split(img,vimg); threshold(vimg[1],imgTemplate,210,255,THRESH_BINARY);// imshow("aa",imgTemplate);}void ZhuangJia::erZhiHua(const Mat &src, Mat &dst, uchar yz){ vector<Mat> bgr; Mat m; //亮度调整 liangDuTiaoZheng(src,m,1,-120); split(m, bgr); dst.create(src.size(),CV_8UC1); imgG = bgr[1]; imgD = diColor == RED ? bgr[2] : bgr[0]; //二值化 uchar *ptrg = imgG.data, *ptrd = imgD.data, *ptrer = dst.data; const uchar *ptrend = imgG.data + imgG.rows*imgG.cols; for(; ptrg != ptrend; ptrg++,ptrd++,ptrer++) { *ptrer = (*ptrd - *ptrg) > yz ? 255 : 0; }// imshow("huidu",dst);}void ZhuangJia::liangDuTiaoZheng(const Mat &src, Mat &dst, double k, double b){ liangDu = b; dst.create(src.size(),src.type()); uchar *ptrsrc = src.data, *ptrdst = dst.data; const uchar *ptrend = src.data + src.cols*src.rows *3; for(; ptrsrc != ptrend; ptrsrc++, ptrdst++) { int val =(int)(k * (*ptrsrc) + b); if(val < 0) val = 0; if(val > 255) { val = 255; cout<<val; } (*ptrdst) = val; }}vector<RotatedRect> ZhuangJia::xunZhaoJuXing(const Mat &img){ vector<RotatedRect> vr; Mat temp,cz; vector<vector<Point> > contour; bool bflag = false; RotatedRect rect; Mat ele(5,5,CV_8U,Scalar(1)); dilate(img,temp,ele);//膨胀 erode(temp,cz,ele);//腐蚀// imshow("cz",cz); //查找轮廓 findContours(cz,contour,RETR_CCOMP , CHAIN_APPROX_SIMPLE); //如果轮廓过小,表明装甲距离过远,多做几次闭运算 int sum = 0,count = 0; for(int i = 0; i < (int)contour.size(); i++){ if(contour[i].size() > 5){ sum += contour[i].size(); count++; } } if(sum / count < 15){// cout<<sum / (int)contour.size(); for(int i = 0; i < 10; i++){ dilate(cz,temp,ele);//膨胀 erode(temp,cz,ele);//腐蚀 } findContours(cz,contour,RETR_CCOMP , CHAIN_APPROX_SIMPLE); juLiYuZhi = 70; jianCeBianChang = 0; isFar = true;//距离过远标志 }else{ isFar = false; }// imshow("cz",cz);// cout<<contour.size()<<endl;// Mat tt = Mat::zeros(cz.rows, cz.cols, CV_8UC3);// tt.create(cz.size(),CV_8UC3);// drawContours(tt,contour,-1,Scalar(0,0,255));// imshow("tt",tt);// for(int i = 0; i < (int)contour.size(); i++){// cout<<contour[i].size()<<" ";// } for(int i = 0; i < (int)contour.size();i++){// cout<<contour[i].size()<<endl; if(contour[i].size() > 5){ bflag = true; //寻找符合条件的轮廓 rect = fitEllipse(contour[i]);// cout<< rect.center<<" "; int rc = rect.center.x, rr = rect.center.y; if(rc-1>0 && rc+1<imgwidth && rr-1>0 && rr+1<imgheight){ for(int ri = -1; ri < jianCeBianChang; ri++){ for(int rj = -1; rj < jianCeBianChang; rj++){// cout<<(int)imgD.at<uchar>(rr+ri,rc+rj)<<endl; if(imgD.at<uchar>(rr+ri,rc+rj) < (255+liangDu-juLiYuZhi)){// cout<<(int)imgD.at<uchar>(rr+ri,rc+rj)<<" "; bflag = false; break; } } if(!bflag) break; } if(bflag){// cout<<endl<<i<<"; "; vr.push_back(rect);// Mat tt;// for(int i = 0; i < vr.size();i++){// tt.create(cz.size(),CV_8UC3);// huaChuMuBiao(tt,rect);// imshow("tt",tt);// } bflag = false; } } } }#ifdef DEBUG cout<<"轮廓个数"<<vr.size()<<endl;#endif if(isFar){ juLiYuZhi = 15; jianCeBianChang = 2; }// cout<<isFar<<endl; return vr;}vector<RotatedRect> ZhuangJia::niHeMuBiao(vector<RotatedRect> vr){ vector<RotatedRect> vrect; RotatedRect rect; int nL, nW; const double tAngleThre = 15, tSizeThre = 3; double dAngle; vrect.clear(); if (vr.size() < 2) //如果检测到的旋转矩形个数小于2,则直接返回 return vrect; //寻找目标 for (int ni = 0; ni < (int)vr.size() - 1; ni++) //求任意两个旋转矩形的夹角 { for (int nj = ni + 1; nj < (int)vr.size(); nj++) { dAngle = abs(vr[ni].angle - vr[nj].angle); while (dAngle > 180) dAngle -= 180; //判断这两个旋转矩形是否是一个装甲的两个LED等条// cout<<dAngle; if ((dAngle < tAngleThre || 180 - dAngle < tAngleThre) && abs(vr[ni].size.height - vr[nj].size.height) < (vr[ni].size.height + vr[nj].size.height) / tSizeThre && abs(vr[ni].size.width - vr[nj].size.width) < (vr[ni].size.width + vr[nj].size.width) / tSizeThre) {//cout<<"here"; rect.center.x = (vr[ni].center.x + vr[nj].center.x) / 2; //装甲中心的x坐标 rect.center.y = (vr[ni].center.y + vr[nj].center.y) / 2; //装甲中心的y坐标 rect.angle = (vr[ni].angle + vr[nj].angle) / 2; //装甲所在旋转矩形的旋转角度 if (180 - dAngle < tAngleThre) rect.angle += 90; nL = (vr[ni].size.height + vr[nj].size.height) / 2; //装甲的高度 nW = sqrt((vr[ni].center.x - vr[nj].center.x) * (vr[ni].center.x - vr[nj].center.x) + (vr[ni].center.y - vr[nj].center.y) * (vr[ni].center.y - vr[nj].center.y)); //装甲的宽度等于两侧LED所在旋转矩形中心坐标的距离// if (nL < nW)// { rect.size.height = nL; rect.size.width = nW;// }// else// {// rect.size.height = nW;// rect.size.width = nL;// } if(rect.size.width/rect.size.height < 4 && rect.size.width/rect.size.height > 2){// cout<<"宽高比"<<rect.size.width/rect.size.height<<endl; vrect.push_back(rect); //将找出的装甲的旋转矩形保存到vector } } } }#ifdef DEBUG cout<<"目标个数"<<vrect.size()<<endl;#endif return vrect;}RotatedRect ZhuangJia::xunZhaoZuiJia(vector<RotatedRect> vr){ RotatedRect rect; if(vr.size() < 1) return rect; if(vr.size() == 1){ rect = vr[0]; return rect; } //利用模板寻找最佳目标 Mat roi; int dist = imgTemplate.cols * imgTemplate.rows; const double pi = 3.1415926; if(imgTemplate.cols < 5 && imgTemplate.rows < 5){ cout<<"no template"<<endl; return rect; } double dangle, a, l; int ic1,ic2,ir1,ir2; int yuZhi = isFar ? 70 : 15; //模板与目标根据最小距离得到最佳 for(int i = 0; i < (int)vr.size(); i++){// cout<<i<<endl; //选出目标区域 dangle = vr[i].angle; while(dangle > 90) dangle -= 180; a = dangle*pi/180; l = vr[i].size.width / (cos(a) * 2);// cout<<"yizu"<<vr[i].size.width<<endl<<vr[i].size.height<<endl<<vr[i].angle<<endl;// cout<<vr[i].size.width<<endl<<a<<endl<<cos(a)<<endl<<l<<endl<<endl; ic1 = vr[i].center.x - l; ic2 = vr[i].center.x + l; ir1 = vr[i].center.y - vr[i].size.height/4; ir2 = vr[i].center.y + vr[i].size.height/4; if(ic1 < 0 || ic2 > imgwidth || ir1 < 0 || ir2 > imgheight){ continue; } roi = imgG(Range(ir1,ir2),Range(ic1,ic2));// imshow("roi",roi); //计算距离 int d = jiSuanjuLi(roi,yuZhi); if(dist > d){ rect = vr[i]; dist = d; } }#ifdef DEBUG cout<<"找到最佳"<<endl;#endif return rect;}void ZhuangJia::huaChuMuBiao(Mat img, RotatedRect vr){ Point2f pt[4]; vr.points(pt); //计算二维盒子顶点 line(img, pt[0], pt[1], CV_RGB(0, 0, 255), 2, 8, 0); line(img, pt[1], pt[2], CV_RGB(0, 0, 255), 2, 8, 0); line(img, pt[2], pt[3], CV_RGB(0, 0, 255), 2, 8, 0); line(img, pt[3], pt[0], CV_RGB(0, 0, 255), 2, 8, 0);}int ZhuangJia::jiSuanjuLi(const Mat &imgroi, int &yuzhi){ int dist = 0; Mat roi,binary; //大小设置为模板大小 resize(imgroi,roi,Size(imgTemplate.cols,imgTemplate.rows)); threshold(roi,binary,255-yuzhi+liangDu,255,THRESH_BINARY);// imshow("ss",binary); uchar *ptrtemp = imgTemplate.data, *ptrb = binary.data; const uchar *ptrend = imgTemplate.data + imgTemplate.cols*imgTemplate.rows; for(; ptrtemp != ptrend; ptrtemp++,ptrb++){ //对应点不同距离加1 dist += *ptrtemp == *ptrb ? 0 : 1; } return dist;}
3.main文件
#include <opencv2/highgui/highgui.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/core/core.hpp>#include <opencv2/features2d/features2d.hpp>#include <iostream>#include "zhuangjia.hpp"#include "jiaodujiesuan.hpp"using namespace std;using namespace cv;int main(){ Mat img = imread("2.jpg");// VideoCapture cap("RedCar.avi");// VideoCapture cap("1.avi");// Mat img;// while(1){// cap >> img;// imshow("aa",img);// imwrite("2.jpg",img);// if(waitKey(20));//// break;// } Mat imggray; ZhuangJia zj;// int num = 0;// while(1){// cap >> img; zj.erZhiHua(img,imggray,15); //imshow("aa",imggray); vector<RotatedRect> vr; vr = zj.xunZhaoJuXing(imggray); vr = zj.niHeMuBiao(vr); // cout<<vr.size();// for(int i = 0; i < vr.size(); i++){// zj.huaChuMuBiao(img,vr[i]);// cout<<num++;// } RotatedRect rr; JiaoDuJieSuan jdjs; float pitch, yaw; if(vr.size()>0){ rr = zj.xunZhaoZuiJia(vr);// zj.huaChuMuBiao(img,rr); jdjs.huoDeJuXingJiaoDian(rr,img); jdjs.qiuJieJiaoDu(pitch,yaw); jdjs.drawPoints(img); cout<<pitch<<" "<<yaw<<endl; } imshow("main",img);// waitKey(50);// } waitKey(0); return 0;}
阅读全文
0 0
- opencv 图像识别程序
- opencv图像识别
- 图像识别---opencv安装
- OpenCV实现图像识别
- Android-图像识别项目OpenCV(2):运行官方例子中的脸部识别程序
- Android-图像识别项目OpenCV(2):运行官方例子中的脸部识别程序
- Android OpenCV图像识别和图像追踪
- Android-图像识别项目OpenCV(3):程序目标以及单独发布
- Android-图像识别项目OpenCV(3):程序目标以及单独发布
- OpenCV人脸识别程序
- 图像识别:Android中使用OpenCV
- 七.使用OpenCv进行图像颜色识别
- 基于OpenCV的细胞图像识别
- android中利用opencv进行图像识别
- opencv图像识别(1-17)
- opencv图像识别(18-37)
- opencv图像识别 0——精通
- opencv程序二:缩放图像
- 索引概述
- C语言之贪心算法
- LeetCode212. Word Search II
- Kotlin发迹史
- MarchingCube实现(C++ OpenGl代码篇)
- opencv 图像识别程序
- C++
- thymleaf基础
- Java面试题准备
- 创建ROS项目并添加第三方库(curl)进行网络请求
- AI担任法庭“书记员”,法律行业是否将因AI发生巨变?
- FIRST集、FOLLOW集 和 SELECT集
- 降低延迟,视频直播APP要这样开发
- EOJ 3298 排队买夜宵