目录
- 看了下貌似有几年没用过算法与C++了,用不到10个小时写的练习项目
- 1. 关键词
- 2. 代码
- Common.h
- BaseModel.h
- BaseView.h
- BaseController.h
- BaseController.cpp
- ViewListener.h
- ModelListener.h
- MainFactry.h
- MainFactry.cpp
- ObjectCheckController.h
- ObjectCheckController.cpp
- CheckHandler.h
- CheckHandler.cpp
- SpeedHandler.h
- SpeedHandler.cpp
- FrameModelSpeed.h
- FrameModelSpeed.cpp
- FrameModelPkg.h
- FrameModelPkg.cpp
- FrameView.h
- FrameView.cpp
- Pkg.h
- Pkg.cpp
- Thread.h
- 3. 待优化
看了下貌似有几年没用过算法与C++了,用不到10个小时写的练习项目
1. 关键词
语言C++ 观察者模式 mvc mvvm 抽象(类) 封装 多态 (虚)基类 虚函数 引用 指针 图像库opencv 多线程等
2. 代码
Common.h
#pragma once
#ifndef COMMON_H
#define COMMON_H
#include <iostream>
using namespace std;
#include<opencv2/opencv.hpp>
using namespace cv;
const int SUCCESS = 0;
const int ERROR = -1;
const int TIME_INTERVAL = 50;
enum copy_state { UNCOPYED = 0, COPYED }; //定义拷贝状态枚举
enum update_state { NOTUPDATE = 0, UPDATE }; //定义更新状态枚举
//工具类
class Common {
public:
static std::time_t getTimeStamp() //毫秒数
{
std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds> tp = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
auto tmp = std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch());
std::time_t timestamp = tmp.count();
//std::time_t timestamp = std::chrono::system_clock::to_time_t(tp);
return timestamp;
}
};
#endif // COMMON_H
BaseModel.h
#pragma once
#ifndef BASE_MODEL_H
#define BASE_MODEL_H
//基础模型类
class BaseModel
{
public:
virtual void empty() {} // 用于编译
};
#endif // BASE_MODEL_H
BaseView.h
#pragma once
#ifndef BASE_VIEW_H
#define BASE_VIEW_H
#include "BaseModel.h"
//基础视图类
class BaseView
{
public:
virtual void init() = 0;
virtual void update(BaseModel* baseModel) = 0;
};
#endif // BASE_VIEW_H
BaseController.h
#pragma once
#ifndef BASE_CONTROLLER_H
#define BASE_CONTROLLER_H
#include "Common.h"
#include "BaseView.h"
#include "BaseModel.h"
#include "ViewListener.h"
#include "ModelListener.h"
//基础控制器类
class BaseController: public ViewListener, public ModelListener
{
private:
list<BaseView*> baseViewList;
list<BaseModel*> baseModelList;
public:
BaseController();
void init(BaseView* baseView, BaseModel* baseModel);
void onViewChanged(BaseView* baseView);
void onModelChanged(BaseModel* baseModel);
void notifyModel(BaseView* baseView);
void notifyView(BaseModel* baseModel);
};
#endif // BASE_CONTROLLER_H
BaseController.cpp
#include "BaseController.h"
BaseController::BaseController()
{
cout<< "创建BaseController" << endl;
}
void BaseController::init(BaseView* baseView, BaseModel* baseModel)
{
cout << "启动BaseController::init" << endl;
this->baseViewList.push_back(baseView);
this->baseModelList.push_back(baseModel);
}
void BaseController::onViewChanged(BaseView* baseView)
{
//cout << "更新BaseController::onViewChanged" << endl;
notifyModel(baseView);
}
void BaseController::onModelChanged(BaseModel* baseModel)
{
//cout << "更新BaseController::onModelChanged" << endl;
notifyView(baseModel);
}
void BaseController::notifyModel(BaseView* baseView)
{
cout << "更新BaseController::notifyModel " << endl;
//list<BaseModel*>::iterator baseModelIterator;
//for (baseModelIterator = baseModelList.begin(); baseModelIterator != baseModelList.end(); baseModelIterator++)
//{
// (*baseModelIterator)->update(baseView);
//}
}
void BaseController::notifyView(BaseModel* baseModel)
{
//cout << "更新BaseController::notifyView " << endl;
list<BaseView*>::iterator baseViewIterator;
if(baseViewList.size() > 0)
for (baseViewIterator = baseViewList.begin(); baseViewIterator != baseViewList.end(); baseViewIterator++)
{
(*baseViewIterator)->update(baseModel);
}
}
ViewListener.h
#pragma once
#ifndef VIEW_LISTENER_H
#define VIEW_LISTENER_H
#include "BaseView.h"
//视图监听器
class ViewListener
{
public:
virtual void onViewChanged(BaseView* baseView) = 0;
virtual void notifyModel(BaseView* baseView) = 0;
};
#endif // VIEW_LISTENER_H
ModelListener.h
#pragma once
#ifndef MODEL_LISTENER_H
#define MODEL_LISTENER_H
#include "BaseModel.h"
//模型监听器
class ModelListener
{
public:
virtual void onModelChanged(BaseModel* baseModel) = 0;
virtual void notifyView(BaseModel* baseModel) = 0;
};
#endif // MODEL_LISTENER_H
MainFactry.h
#pragma once
#ifndef MAIN_FACTORY_H
#define MAIN_FACTORY_H
#include "Common.h"
#include "BaseController.h"
#include "ObjectCheckController.h"
/*
启动类
*/
class MainFactry
{
public:
static void init();
};
#endif // MAIN_FACTORY_H
MainFactry.cpp
#include "MainFactry.h"
//持续优化中
//主函数
int main(const int argc, const char ** argv)
{
cout<< "启动主线程" << endl;
cout<< "argc=" << argc << endl;
if (argc > 0)
{
for (int k = 0; k < argc; k++)
{
cout << "argv=" << argv[k] << endl;
}
}
MainFactry::init();
return SUCCESS;
}
void MainFactry::init()
{
cout<< "启动控制器controller" << endl;
(new ObjectCheckController())->init();
}
ObjectCheckController.h
#pragma once
#ifndef OBJECT_CHECK_CONTROLLER_H
#define OBJECT_CHECK_CONTROLLER_H
#include "Common.h"
#include "BaseController.h"
#include "FrameView.h"
#include "Thread.h"
#include "CheckHandler.h"
#include "SpeedHandler.h"
//物体检测控制器
class ObjectCheckController:public BaseController
{
private:
FrameView* frameView;
CheckHandler* checkHandler;
SpeedHandler* speedHandler;
public:
ObjectCheckController();
void init();
void initDisplay();
void startThread();
};
#endif // OBJECT_CHECK_CONTROLLER_H
ObjectCheckController.cpp
#include "ObjectCheckController.h"
ObjectCheckController::ObjectCheckController()
{
cout << "创建控制器ObjectCheckController" << endl;
frameView = new FrameView();
this->checkHandler = new CheckHandler();
speedHandler = new SpeedHandler();
}
void ObjectCheckController::init()
{
cout<< "启动ObjectCheckController::init()" << endl;
BaseController::init(frameView,NULL);
startThread();
initDisplay();
}
void ObjectCheckController::initDisplay()
{
cout<< "启动视图ObjectCheckController::initDisplay" << endl;
frameView->init();
}
void ObjectCheckController::startThread()
{
cout << "启动2个线程ObjectCheckController::startThread()" << endl;
checkHandler->init(this);
speedHandler->init(this);
}
CheckHandler.h
#pragma once
#ifndef CHECK_HANDLER_H
#define CHECK_HANDLER_H
#include "Common.h"
#include "Thread.h"
#include "FrameModelPkg.h"
#include "ModelListener.h"
#include <core/types_c.h>
#include <core/core_c.h>
#include <imgproc/imgproc_c.h>
extern Mat frameCopy;
extern atomic_int isCopyed;
static FrameModelPkg* frameModelCheck;
static ModelListener* modelListenerCheck;
void runCheck();
Mat convertPic(Mat image);
void checkObject(Mat imageBinary);
//计算矩形线程
class CheckHandler:public Thread
{
public:
CheckHandler();
void init(ModelListener* modelListener);
};
#endif // CHECK_HANDLER_H
CheckHandler.cpp
#include "CheckHandler.h"
CheckHandler::CheckHandler()
{
cout << "创建Checkhandler" << endl;
frameModelCheck = new FrameModelPkg();
}
void CheckHandler::init(ModelListener* listener)
{
cout << "启动Checkhandler::init()" << endl;
modelListenerCheck = listener;
thread checkThread(runCheck);
checkThread.detach();
}
void runCheck()
{
cout<< "运行Checkhandler:: runCheck()" << endl;
for (;;)
{
if (isCopyed == UNCOPYED)
{
}
if (isCopyed == COPYED)
{
checkObject(convertPic(frameCopy));
isCopyed = UNCOPYED;
}
this_thread::sleep_for(std::chrono::milliseconds(TIME_INTERVAL));
}
}
Mat convertPic(Mat image) {
if (image.empty())
{
cout << "convertPic image.empty()" << endl;
return image;
}
Mat gray, binary, element;
cvtColor(image, gray, CV_RGB2GRAY);
threshold(gray, binary, 210, 255, CV_THRESH_TOZERO_INV);
return binary;
}
string path = "D:/PROJECT/res/imageBinary.jpg";
void checkObject(Mat imageBinary)
{
if (imageBinary.empty())
{
cout << "checkObject imageBinary.empty()" << endl;
return ;
}
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(imageBinary, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point());
//cout << "CheckHandler contours.size()=" << contours.size() << endl;
vector<Pkg> pkgs;
for (int i = contours.size() - 1; i >= 0; i--)
{
if (contourArea(contours[i]) <= 6000)
{
continue;
}
Rect2d rect = boundingRect(contours[i]);
Pkg pkg(0,rect.x,rect.y,rect.width,rect.height);
pkgs.push_back(pkg);
}
//imwrite(path, imageBinary);
frameModelCheck->setPkgs(pkgs);
modelListenerCheck->onModelChanged(frameModelCheck);
}
SpeedHandler.h
#pragma once
#ifndef SPEED_HANDLER_H
#define SPEED_HANDLER_H
#include "Common.h"
#include "Thread.h"
#include "FrameModelSpeed.h"
#include "ModelListener.h"
const int SPEED_VECTOR_SIZE = 1;
extern Mat frame;
static Mat curFrame;
static Mat preFrame;
static Mat curr64f, prev64f;
static FrameModelSpeed* frameModelSpeed;
static ModelListener* modelListenerSpeed;
void runSpeed();
void calcSpeed();
//计算速度线程
class SpeedHandler:public Thread
{
public:
SpeedHandler();
void init(ModelListener* modelListener);
};
#endif // SPEED_HANDLER_H
SpeedHandler.cpp
#include "SpeedHandler.h"
SpeedHandler::SpeedHandler()
{
cout << "创建SpeedHandler" << endl;
frameModelSpeed = new FrameModelSpeed();
}
void SpeedHandler::init(ModelListener* listener)
{
cout << "启动SpeedHandler:: init()" << endl;
modelListenerSpeed = listener;
thread speedThread(runSpeed);
speedThread.detach();
}
void runSpeed()
{
cout << "运行SpeedHandler:: runSpeed()" << endl;
calcSpeed();
}
int64 preTimeStamp = Common::getTimeStamp();
int64 curTimeStamp = Common::getTimeStamp();
vector<double> speedVector;
vector<double>::iterator it;
void calcSpeed() {
cout<< "calcSpeed" << endl;
for (;;) {
if (frame.empty())
{
cout << "calcSpeed frame.empty()" << endl;
std::this_thread::sleep_for(std::chrono::milliseconds(TIME_INTERVAL));
continue;
}
cvtColor(frame.clone(), curFrame, COLOR_RGB2GRAY);
curTimeStamp = Common::getTimeStamp();
if (curFrame.empty()) {
cout << "calcSpeed curFrame.empty()" << endl;
continue;
}
if (preFrame.empty()) {
preFrame = curFrame.clone();
preTimeStamp = curTimeStamp;
std::this_thread::sleep_for(std::chrono::milliseconds(TIME_INTERVAL));
continue;
}
preFrame.convertTo(prev64f, CV_64F);
curFrame.convertTo(curr64f, CV_64F);
Point2d shift = phaseCorrelate(prev64f, curr64f);
//double radius = cv::sqrt(shift.x * shift.x + shift.y * shift.y);
//cout<< "SpeedHandler::radius=" << radius << endl;
//cout << "SpeedHandler::curTimeStamp - preTimeStamp=" << curTimeStamp - preTimeStamp << endl;
//double speed = (radius > 2) ? (shift.x) / (curTimeStamp - preTimeStamp) : 0;
double speed = (abs(shift.x) > 15) ? (shift.x) / (curTimeStamp - preTimeStamp) : 0;
//cout << "SpeedHandler::shift.x=" << shift.x << endl;
preFrame = curFrame.clone();
preTimeStamp = Common::getTimeStamp();
if (speedVector.size() >= SPEED_VECTOR_SIZE)
{
speedVector.erase(speedVector.begin());
}
speedVector.push_back(speed);
double sumSpeed = 0;
double avgSpeed = 0;
for (it = speedVector.begin(); it != speedVector.end(); it++)
{
sumSpeed += *it;
}
avgSpeed = sumSpeed / (speedVector.size());
frameModelSpeed->setSpeed(avgSpeed);
modelListenerSpeed->onModelChanged(frameModelSpeed);
std::this_thread::sleep_for(std::chrono::milliseconds(TIME_INTERVAL * 5));
}
}
FrameModelSpeed.h
#pragma once
#ifndef FRAME_MODEL_SPEED_H
#define FRAME_MODEL_SPEED_H
#include "Common.h"
#include "BaseModel.h"
//模型-速度类
class FrameModelSpeed :public BaseModel
{
private:
double speed;
public:
void setSpeed(double speed);
double getSpeed();
};
#endif // FRAME_MODEL_SPEED_H
FrameModelSpeed.cpp
#include "FrameModelSpeed.h"
void FrameModelSpeed::setSpeed(double speed)
{
this->speed = speed;
}
double FrameModelSpeed::getSpeed()
{
return speed;
}
FrameModelPkg.h
#pragma once
#ifndef FRAME_MODEL_RECT_H
#define FRAME_MODEL_RECT_H
#include "Common.h"
#include "BaseModel.h"
#include "Pkg.h"
//模型-矩形类
class FrameModelPkg :public BaseModel
{
private:
vector<Pkg> pkgs;
public:
void setPkgs(vector<Pkg> pkgs);
vector<Pkg> getPkgs();
};
#endif // FRAME_MODEL_RECT_H
FrameModelPkg.cpp
#include "FrameModelPkg.h"
void FrameModelPkg::setPkgs(vector<Pkg> pkgs)
{
this->pkgs = pkgs;
}
vector<Pkg> FrameModelPkg::getPkgs()
{
return pkgs;
}
FrameView.h
#pragma once
#ifndef FRAME_VIEW_H
#define FRAME_VIEW_H
#include "Common.h"
#include "BaseView.h"
#include "FrameModelPkg.h"
#include "FrameModelSpeed.h"
static mutex mutexPkgs;
//static mutex mutexSpeed;
const int PKGS_VECTOR_SIZE = 2;
static vector<vector<Pkg>> pkgsVector;
//显示视图类
class FrameView : public BaseView
{
private:
atomic<double> speed = 0;
vector<Pkg> pkgs;
public:
FrameView();
void init();
void update(BaseModel* baseModel);
void checkVideo(string videoFilePath);
void display();
vector<Pkg> checkPkgs();
void setSpeed(double speed);
double getSpeed();
void setPkgs(vector<Pkg> pkgs);
vector<Pkg> getPkgs();
};
#endif // FRAME_VIEW_H
FrameView.cpp
#include "FrameView.h"
const string WINDOW_NAME = "物体检测图片";
const string& videoFilePath = "";
//存储帧图像
Mat frame;
//图像帧拷贝
Mat frameCopy;
atomic_int isCopyed = UNCOPYED;
FrameView::FrameView()
{
cout << "创建FrameView" << endl;
}
void FrameView::init()
{
cout<< "启动FrameView::init()" << endl;
checkVideo(videoFilePath);
}
void FrameView::setSpeed(double speed)
{
this->speed = speed;
}
double FrameView::getSpeed() {
return speed;
}
void FrameView::setPkgs(vector<Pkg> pkgs)
{
this->pkgs = pkgs;
}
vector<Pkg> FrameView::getPkgs()
{
return pkgs;
}
void FrameView::update(BaseModel* baseModel)
{
//cout << "更新FrameView::update" << endl;
if (baseModel == NULL)
{
cout << "baseModel == NULL" << endl;
return;
}
if (dynamic_cast<FrameModelSpeed*>(baseModel))
{
double updateSpeed = ((FrameModelSpeed*)baseModel)->getSpeed();
//cout << "FrameView::updateSpeed=" << updateSpeed << endl;
if (abs(updateSpeed) < 1)
{
if (abs(updateSpeed) <= 0.1)
{
//mutexSpeed.lock();
speed = 0;
//mutexSpeed.unlock();
//cout << "FrameView::updateSpeed=" << 0 << endl;
}
else {
//mutexSpeed.lock();
if (abs(updateSpeed - speed) >= 0.1)
{
speed = updateSpeed;
//cout << "FrameView::updateSpeed=" << updateSpeed << endl;
}
//mutexSpeed.unlock();
}
}
}
if (dynamic_cast<FrameModelPkg*>(baseModel))
{
//cout << "FrameView::UpdatePkg" << endl;
vector<Pkg> updatePkgs = ((FrameModelPkg*)baseModel)->getPkgs();
if (pkgsVector.size() >= PKGS_VECTOR_SIZE)
{
pkgsVector.erase(pkgsVector.begin());
}
pkgsVector.push_back(updatePkgs);
updatePkgs = checkPkgs();
mutexPkgs.lock();
setPkgs(updatePkgs);
mutexPkgs.unlock();
}
}
string framePath = "D:/PROJECT/res/frame.jpg";
int64 t2 = Common::getTimeStamp();
void FrameView::checkVideo(string path)
{
cout << "checkVideo path=" << path << endl;
VideoCapture capture(videoFilePath, 0);
if (!capture.isOpened())
{
cout << "打开视频异常" << endl;
system("pause");
}
int64 lTimeStamp = 0;
for (;waitKey(1) != 'q';)
{
t2 = Common::getTimeStamp();
capture >> frame;
if (!frame.empty()) {
//采集频率X毫秒帧图像
if ((isCopyed == UNCOPYED) && ((Common::getTimeStamp() - lTimeStamp) >= (TIME_INTERVAL * 3)))
{
frameCopy = frame.clone();
isCopyed = COPYED;
lTimeStamp = Common::getTimeStamp();
}
display();
cout << "主线程用时:" << Common::getTimeStamp() - t2 << endl;
}
else {
//停止
cout<< "视频空" << endl;
break;
}
}
capture.release();
}
vector<Pkg>::iterator it;
void FrameView::display()
{
Mat frame1 = frame.clone();
mutexPkgs.lock();
if (!pkgs.empty())
{
for (it = pkgs.begin();it != pkgs.end();it++)
{
Rect rect((*it).x, (*it).y,(*it).width,(*it).height);
rectangle(frame1, rect, Scalar(0, 0, 255), 2, 1, 0);
}
}
mutexPkgs.unlock();
imshow(WINDOW_NAME, frame1);
}
// 计算更新
vector<Pkg> FrameView::checkPkgs()
{
vector<Pkg> pkgTemp = pkgs;
if (pkgsVector.size() == PKGS_VECTOR_SIZE)
{
vector<Pkg> pkg0 = pkgsVector[0];
vector<Pkg> pkg1 = pkgsVector[1];
//vector<Pkg>::iterator iterator0;
//vector<Pkg>::iterator iterator1;
if ((pkg0.size() == pkg1.size())&&(pkg0.size() == pkgTemp.size()))
{
//cout << "pkg0.size()=" << pkg0.size() << endl;
//cout << "pkg1.size()=" << pkg1.size() << endl;
//cout << "pkgTemp.size()=" << pkgTemp.size() << endl;
for (int k = pkg0.size() -1;k >= 0; k--)
{
if ((k == 0) || (k == (pkg0.size() - 1)))
{
Rect rect0(pkg0[k].x, pkg0[k].y, pkg0[k].width, pkg0[k].height);
Rect rect1(pkg1[k].x, pkg1[k].y, pkg1[k].width, pkg1[k].height);
//double area0 = (rect0 & rect1).area();
//double area1 = (rect0 | rect1).area();
//if ((area0 / area1)> 1.1)
{}
double area0 = rect0.area();
double area1 = rect1.area();
double area = area0 / area1;
//cout << "rect0.area()=" << area0 << endl;
//cout << "rect1.area()=" << area1 << endl;
//cout << "area0/area1=" << area << endl;
if ((area < 0.95) || (area > 1.06))
{
//cout << "checkPkgs update" << endl;
pkgTemp[k].x = pkg1[k].x; //(pkgTemp[k].x - pkg1[k].x) < 5? pkgTemp[k].x: pkg1[k].x;
pkgTemp[k].y = pkg1[k].y; //(pkgTemp[k].y - pkg1[k].y) < 2 ? pkgTemp[k].y : pkg1[k].y;
pkgTemp[k].width = pkg1[k].width; //(pkgTemp[k].width - pkg1[k].width) < 5 ? pkgTemp[k].width : pkg1[k].width;
pkgTemp[k].height = pkg1[k].height; //(pkgTemp[k].height - pkg1[k].height) < 2 ? pkgTemp[k].height : pkg1[k].height;
}
else
{
//cout << "checkPkgs movex speed=" << speed << endl;
//mutexSpeed.lock();
double movex = speed * 65.0;
//mutexSpeed.unlock();
//cout<< "movex=" << movex << endl;
pkgTemp[k].x += movex;
}
}
}
}
else {
return pkg1;
}
}
return pkgTemp;
}
Pkg.h
#pragma once
#ifndef PKG_H
#define PKG_H
#include "Common.h"
class Pkg
{
public:
long number;
double x;
double y;
double width;
double height;
int update;
Pkg(long number,double x, double y, double width, double height, int update = NOTUPDATE);
};
#endif // PKG_H
Pkg.cpp
#include "Pkg.h"
Pkg::Pkg(long number,double x, double y, double width, double height, int update)
{
this->number = number;
this->x = x;
this->y = y;
this->width = width;
this->height = height;
this->update = update;
}
Thread.h
#pragma once
#ifndef THREAD_H
#define THREAD_H
#include "Common.h"
#include <thread>
//基础线程类
class Thread
{
public:
virtual void run() {};
};
#endif // THREAD_H
3. 待优化
架构设计(已更新部分)
增加namespace
基本类的函数(构造 拷贝构造 析构等)
资源占用 (已更新部分)
多线程执行(已更新部分)
模板方式封装
效率等(已更新部分)