opencv矩形聚类识别及输出

矩形聚类参考文献
以下为上面参考文献的完整代码
使用ubuntu16.04 opencv3.4.1 Qt5.9.0

#include "cv.h"
#include"highgui.hpp"
#include"imgproc.hpp"
#include"opencv.hpp"

#define MIN_SQUARE_AREA 100 
#define MIN_CENTER_DIS 10

using namespace cv;
using namespace std;

double otsuThreshold(IplImage* img);
void FindSquares( IplImage* src, CvSeq* squares, CvMemStorage* storage, vector<Point> &squares_centers, vector< vector<Point> > &squares_v, Point pt );
void drawSquares( IplImage* img_, CvSeq* squares ,const char* wndname);
void CenterClassification( vector<Point> &squares_centers,   vector< vector<int> > &result);
double ComputeDistance (CvPoint pointO,CvPoint pointA );

const char* wndname = "Square Detection Demo";
CvSeq* squares_ = 0;
CvMemStorage* storage_ = NULL;
vector<Point> squares_centers_;
vector< vector<Point> > squares_v_;
Point pt_;

int main(int argc, char *argv[])
{
    CvCapture* capture = 0;
    capture = cvCaptureFromCAM(0);
//    while (1)
//    {
//       IplImage* frame = 0;
//       frame = cvQueryFrame( capture );
       IplImage* frame = cvLoadImage("/home/lv/1.png");
       IplImage* image = 0;
       image = cvCreateImage( cvGetSize(frame), 8, 1 );
       cvCvtColor(frame,image,CV_BGR2GRAY);
       IplImage* image_threshold;
       image_threshold = cvCreateImage( cvGetSize(frame), 8, 1 );
       double threshold_ = otsuThreshold(image);
       cvThreshold(image,image_threshold,threshold_,255,CV_THRESH_BINARY);
       cvShowImage("阈值化图像",image_threshold);
       if( storage_ == NULL)
       {
           storage_ = cvCreateMemStorage(0);
       } else {
           cvClearMemStorage(storage_);
       }
       CvSeq* squares_ = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvPoint), storage_ );
       FindSquares(image_threshold,squares_,storage_,squares_centers_,squares_v_,pt_);
       drawSquares(frame, squares_, wndname);
       vector< vector<int> > result_;
       result_.clear();
       CenterClassification(squares_centers_,result_);


      cvWaitKey(0);

//       char c=waitKey(30); //延时30毫秒
//       if (c == 27) //按ESC键退出
//           break;
//    }
}

double otsuThreshold(IplImage* img)
{
    double T = 0;
    int height = img->height;
    int width  = img->width;
    int step   = img->widthStep;
    uchar* data  = (uchar*)img->imageData;
    double gSum0;
    double gSum1;
    double N0 = 0;
    double N1 = 0;
    double u0 = 0;
    double u1 = 0;
    double w0 = 0;
    double w1 = 0;
    double tempg = -1;
    double g = -1;
    double Histogram[256]={0};// = new double[256];
    double N = width*height;
    for(int i=0;i<height;i++)
    {
        for(int j=0;j<width;j++)
        {
            double temp =data[i*step + j * 3] * 0.114 + data[i*step + j * 3+1] * 0.587 + data[i*step + j * 3+2] * 0.299;
            temp = temp<0? 0:temp;
            temp = temp>255? 255:temp;
            Histogram[(int)temp]++;
        }
    }

    for (int i = 0;i<256;i++)
    {
        gSum0 = 0;
        gSum1 = 0;
        N0 += Histogram[i];
        N1 = N-N0;
        if(0==N1)break;
        w0 = N0/N;
        w1 = 1-w0;
        for (int j = 0;j<=i;j++)
        {
            gSum0 += j*Histogram[j];
        }
        u0 = gSum0/N0;
        for(int k = i+1;k<256;k++)
        {
            gSum1 += k*Histogram[k];
        }
        u1 = gSum1/N1;
        //u = w0*u0 + w1*u1;
        g = w0*w1*(u0-u1)*(u0-u1);
        if (tempg<g)
        {
            tempg = g;
            T = i;
        }
    }
    return T;
}
//找四边形
void FindSquares( IplImage* src, CvSeq* squares, CvMemStorage* storage, vector<Point> &squares_centers, vector< vector<Point> > &squares_v, Point pt )
{
    CvSeq* cv_contours;    // 边缘
    CvSeq* result;         // the result of detecting squares
    CvSeqReader reader;    // the pointer to read data of "result"
    CvPoint corner[4];
    vector<Point> corner_v;
    Point temp;
    Point center;
    cvFindContours( src, storage, &cv_contours, sizeof(CvContour),CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, pt ); //find contours

    while(cv_contours) 
    {
        if( fabs(cvContourArea(cv_contours)) > MIN_SQUARE_AREA )   //neglect the small contours
        {
                        //findout the squares
            result = cvApproxPoly( cv_contours, sizeof(CvContour), storage, CV_POLY_APPROX_DP, cvContourPerimeter(cv_contours)*0.02, 0 );
            if( result->total == 4  &&  cvCheckContourConvexity(result))
            {
                cvStartReadSeq( result, &reader, 0 );
                for( int i = 0; i < 4; i++ )
                {
                    cvSeqPush( squares,(CvPoint*)cvGetSeqElem( result, i ));
                    memcpy( corner + i, reader.ptr, result->elem_size );
                    CV_NEXT_SEQ_ELEM( result->elem_size, reader );
                }
                for(int i =0; i < 4; i++)    //save the corner points to corner_v, it will help us process the data
                {
                    temp = corner[i];
                    corner_v.push_back(temp);
                }
                center.x = (corner[0].x + corner[1].x + corner[2].x + corner[3].x) / 4;
                center.y = (corner[0].y + corner[1].y + corner[2].y + corner[3].y) / 4;                
                squares_centers.push_back(center);
                squares_v.push_back(corner_v);
                corner_v.clear();
            }
        }
        cv_contours = cv_contours->h_next;
    }
        //auto iter = squares_centers.begin();
        for(int i = 0;i<squares_centers.size();i++)
        {
            cout <<i<<":"<< squares_centers[i]<< endl;
        }
        cout<<endl;
}
//画出找到的矩形
void drawSquares( IplImage* img_, CvSeq* squares ,const char* wndname)
{
    CvSeqReader reader;
    IplImage* cpy = cvCloneImage( img_ );
    CvPoint pt[4];
    int i;
    cvStartReadSeq( squares, &reader, 0 );
    for( i = 0; i < squares->total; i += 4 )
    {
        CvPoint* rect = pt;
        int count = 4;
        memcpy( pt, reader.ptr, squares->elem_size );
        CV_NEXT_SEQ_ELEM( squares->elem_size, reader );
        memcpy( pt + 1, reader.ptr, squares->elem_size );
        CV_NEXT_SEQ_ELEM( squares->elem_size, reader );
        memcpy( pt + 2, reader.ptr, squares->elem_size );
        CV_NEXT_SEQ_ELEM( squares->elem_size, reader );
        memcpy( pt + 3, reader.ptr, squares->elem_size );
        CV_NEXT_SEQ_ELEM( squares->elem_size, reader );
        cvPolyLine( cpy, &rect, &count, 1, 1, CV_RGB(0,255,0), 3, CV_AA, 0 );
        //cvPolyLine( cpy, &rect, &count, 1, 1, CV_RGB(0,255,0), 1, CV_AA, 0 );//彩色绘制
    }
    cvShowImage( wndname, cpy );
    cvReleaseImage( &cpy );
}

void CenterClassification( vector<Point> &squares_centers, vector< vector<int> > &result)
{
    vector<int> centers_index;
    vector<int> result_temp;
    int index_i;
    int index_j;
    for(int i = 0; i < squares_centers.size(); i++)
    {
        centers_index.push_back(i);    //save the index of squares centers
    }

    for(int i = 0; i < centers_index.size(); i++)
        {   
            result_temp.push_back(centers_index[i]);
            for(int j = i + 1; j < centers_index.size(); j++)
            {   
                index_i = centers_index[i];
                index_j = centers_index[j];
                if( ComputeDistance( squares_centers[index_i], squares_centers[index_j] ) < MIN_CENTER_DIS )
                {   
                    result_temp.push_back(centers_index[j]);
                    centers_index.erase(centers_index.begin() + j );
                    j--;
                }
            }
            result.push_back(result_temp);
            auto iter = result_temp.begin();cout<<"聚类:[";
                for(;iter != result_temp.end(); ++iter)
                {
                  cout<<*iter<<" ";
                }
            cout<<"]";
            cout<<endl;
            result_temp.clear();
        }
        auto it = result.begin();
        int x = (*it).size();int xx =0;int count=1;//x为聚类的矩形形心个数
        for (it=result.begin()+1;it!=result.end();++it)
        {
             if (x < (*it).size())
             {x = (*it).size();xx= count;}
             count++;

        }
//xx为最大矩形聚类size所在位置
        if (x == 5){
        double zd_x =0 ,zd_y = 0;
        for(int lw = 0;lw<x;lw++)
        {   
             zd_x = zd_x+squares_centers[result[xx][lw]].x;
             zd_y = zd_y+squares_centers[result[xx][lw]].y;
        }
        //输出聚类的矩形平均形心位置
        cout<<"location:["<<zd_x/x<<","<<zd_y/x<<"]"<<endl;
        }
        squares_centers.clear();
}

double ComputeDistance (CvPoint pointO,CvPoint pointA )
{
    double distance;
    distance = powf((pointO.x - pointA.x),2) + powf((pointO.y - pointA.y),2);
    distance = sqrtf(distance);
    return distance;
}

效果如下:
1.png
在这里插入图片描述在这里插入图片描述

2020.7.29 in nwpu

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值