1. 程式人生 > >opencv 影象識別程式

opencv 影象識別程式

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
#endif

ZhuangJia::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;
}

相關推薦

opencv 影象識別程式

1.標頭檔案 #pragma once #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/im

opencv影象識別訓練例項

我一度以為影象訓練會很難,覺得很高深,直到我親自做了一個影象的訓練才認識到如果僅僅是單純地學習和使用,真的很簡單。 本文按照如下順序來進行詳細解釋如何進行影象識別訓練過程: 製作影象 影象資料 影象訓練 影象識別例項 選取影象集 我這裡下載了12張楊冪的照

Opencv影象識別從零到精通(33)----moravec角點、harris角點

一、角點     影象處理和與計算機視覺領域,興趣點(interest points),或稱作關鍵點(keypoints)、特徵點(feature points) 被大量用於解決物體識別,影象識別、影象匹配、視覺跟蹤、三維重建等一系列的問題。我們不再觀察整幅圖,而是選擇某些

Opencv影象識別從零到精通(24)------漫水填充,種子填充,區域生長、孔洞填充

         可以說從這篇文章開始,就結束了影象識別的入門基礎,來到了第二階段的學習。在平時處理二值影象的時候,除了要進行形態學的一些操作,還有有上一節講到的輪廓連通區域的面積周長標記等,還有一個最常見的就是孔洞的填充,opencv這裡成為漫水填充,其實也可以叫種子填

Opencv影象識別從零到精通(37)----KNN演算法

#include <opencv2/ml/ml.hpp> #include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp>

Opencv影象識別從零到精通(32)----直方圖對比,模版匹配,方向投影

0、預備知識 歸一化就是要把需要處理的資料經過處理後(通過某種演算法)限制在你需要的一定範圍內。 函式原型: <span style="font-size:18px;">void normalize(InputArray src,OutputArray dst

opencv影象識別技術在自動化測試中的應用

在自動化測試中,基於xpath、js選擇器、css選擇器進行元素定位及判定的技術已經比較成熟。在實際應用中,無論是web端還是移動端,仍有很多時候需要根據頁面內容、頁面中的影象進行定位及判定,這裡介紹一下基於opencv的影象識別技術在自動化測試中的應用。 這裡我們使用sel

Android OpenCV影象識別影象追蹤

首先介紹一下OpenCV中影象識別和跟蹤機制:        影象跟蹤機制是確定矩目標在3D環境中的姿態,並根據此類資訊環繞目標物件繪製輪廓線。在最終的2D影象中,考慮到目標可能相對於相機傾斜,因而輪廓線將呈現為四邊形(不一定是矩形)。        上述跟蹤機制主要包含以

Opencv影象識別從零到精通(21)-----canny運算元邊緣檢測

          最後來看看canny運算元,這個是被成為最好的運算元,因為過程多,有準測,後面會列出來,也是邊緣檢測的最後一個,所以這裡作為結尾,來看看各個邊緣檢測的效果。 邊緣檢測結果比較

Python+opencv影象識別

影象識別 最近工作遇到了一個需要識別安全鍵盤並點選的需求,做自動化嘛,由於安全鍵盤的鍵位固定但是鍵值隨機,所以常規的方法不能正確獲取觸發點選,so,上網查了一下基本思路都是用機器識別。 載入opencv-python pip install opencv-python View Cod

影象識別opencv-第一個程式(1)

==============開新坑====撒花撒花=========== 聽說opencv結合AR可以玩的很6,於是新坑就開了。 沒有什麼理由,只是熱愛技術。 ================吐槽完畢======== 關於搭建環境什麼的就不說了 ,直接上程式,順便提醒下,

Android-影象識別專案OpenCV(2):執行官方例子中的臉部識別程式

3、下載OpenCV4Android官方SDK並進行匯入   SDK下載地址:http://pt.sourceforge.jp/frs/g_redir.php?m=jaist&f=%2Fopencvlibrary%2Fopencv-android%2F2.4.2%2

【備忘】從基礎到深度學習OpenCV視訊教程計算機視覺影象識別實戰Python C C++

├─第01講 工欲善其事必先利其器-影象處理基礎 │      cv第一次資料.rar │      第一課.mkv │      ├─第02講 初探計算機視覺 │      cv_第一二講.pdf │      cv第二次資料.rar │      第二課.mkv │  

VC++ 利用Opencv 做的一個發票識別程式識別有誤

如題,如圖 上圖為識別有誤樣張,下圖為識別正常樣張。 現在是簡單的貼票識別沒問題,但是較複雜的貼票就會識別有誤,識別不全,請教大家誰能幫我看下原因? 程式碼段: void do_bill_image(const char* pTifFile) {    &nbs

android中利用opencv進行影象識別

之前開發的時候老大讓研究下影象識別的功能,同事推薦看看opencv,發現對於移動端來說opencv的資料和demo都比較少,現在整理下之前的工作成果。 首先是進行配置工作,先匯入opencv的一個程式碼模組 之後是匯入opencv的具體的演算法,當然是c

opencv svm 折騰的識別程式

前面有過用halcon識別字符,現在用opencv折騰下。比較一下 排除svm演算法的問題,對我們來說就是構建合適的分類資料, 在這還是採用《Mastering OpenCV with Practical Computer Vision》中說的 水平方向字元投影 + 豎直方

使用opencv的dnn模組進行影象識別

專案地址:https://github.com/zhongqianli/cifar10_classification.git opencv3.4的dnn模組已經支援caffe、tensorflow、pytorch等主流深度學習框架訓練的模型。 本文用caffe預先在cifar10

OpenCV實現影象識別

最近參加了一個機器人比賽,本人負責影象識別和串列埠通訊方面的任務工作。串列埠通訊的教程可以見我的部落格;下面主要總結一下我對影象識別的整個學習過程。 開發環境 Mac OS Xcode C++ OpenCV 2.4.12 思考過程 實現影象識別

Android-影象識別專案OpenCV(4):開發思路以及問題

六、開發思路   搭建好環境和做好各種準備功夫,接下來就開始我們的開發之路。   首先,我們先檢視一下官方教程文件,看有沒有我們需要的例子。我找到了一個二維影象識別的例子:      這個教程是用C++寫的,用計算特徵點來比對兩幅影象。如果我們用這個演算法可得到特徵點的匹

iOS中使用opencv進行影象識別操作(一)步驟很多,這一篇只是講了第一步.

前言OpenCV ,是一個開源的跨平臺計算機視覺和機器學習庫,通俗點的說,就是他給計算機提供了一雙眼睛,一雙可以從圖片中獲取資訊的眼鏡,從而完成人臉識別、去紅眼、追蹤移動物體等等的影象相關的功能。更多具體的說明可參見 OpenCV 官網。匯入工程匯入 OpenCV 到 Xco