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;}
原创粉丝点击