此案例的需求:编写一个物体检测的SDK,已知需求要满足多种设备,图片文件夹、视频、网络摄像头、usb摄像头等,同时要稳定识别并输出识别结果、且将识别到的物体抠图出来。后续可能会有其它操作需要。
分析:变化-数据源和操作两个变化维度
其中数据源行为:初始化、获取单图、关闭资源
操作:初始化、run需要进行的操作、running具体的调用数据资源执行操作
第一版完成目标:读取文件夹里面的图片,将识别到的物体抠图出来。
BaseImgSource与BaseOperation之间用的是桥模式的思想,使用组合来扩展两个维度的变化。
BaseImgSource与其子类OperationSaveObjRect之间用的是模板方法,重写run方法,外部调用Running方法来执行预先设置的操作流程。
BaseImgSource.h 工厂方法
#pragma once
#ifndef BASEIMGSOURCE_H
#define BASEIMGSOURCE_H
#include
#include "opencv2/opencv.hpp"
// 图片数据源抽象类
class BaseImgSource
{
public:
// 初始化
virtual bool Init(std::string _mess = "") = 0;
// 获取图片
virtual bool GetMat(cv::Mat & _mat) = 0;
// 关闭
virtual bool Close() = 0;
virtual ~BaseImgSource(){};
};
// 工厂基类
class ImgSourceFactory
{
public:
virtual BaseImgSource* CreateImgSource()=0;
virtual ~ImgSourceFactory() {};
};
#endif // !BASEIMGSOURCE_H
ImgSetSource.h
#pragma once
#ifndef IMGSETSOURCE_H
#define IMGSETSOURCE_H
#include "BaseImgSource.h"
// 图片数据集
class ImgSetSource : public BaseImgSource
{
public:
// 初始化
virtual bool Init(std::string _mess = "");
// 获取图片
virtual bool GetMat(cv::Mat & _mat);
// 关闭
virtual bool Close();
~ImgSetSource() {};
};
class ImgSetSourceFactory : public ImgSourceFactory
{
public :
virtual ImgSetSource* CreateImgSource()
{
return new ImgSetSource();
}
};
#endif // !IMGSETSOURCE_H
ImgSetSource.cpp
#include "ImgSetSource.h"
bool ImgSetSource::Init(std::string _mess)
{
// 打开文件夹,读取文件列表
// 如果文件列表为空,则返回false
return false;
}
bool ImgSetSource::GetMat(cv::Mat & _mat)
{
// 按照打开文件列表的顺序依次读取图片
return false;
}
bool ImgSetSource::Close()
{
// 关闭打开的文件
return false;
}
BaseOperation.h 策略模式
Running为模板方法的应用
#pragma once
#ifndef BASEOPERATION_H
#define BASEOPERATION_H
#include "BaseOperation.h"
#include "../ImgSource/BaseImgSource.h"
#include "../Recognition/Recognition.h"
// 图片数据源基类
class BaseOperation
{
public:
// 在Running中调用Run()
void Running(cv::Mat _mat);
virtual ~BaseOperation() {
delete m_imgSource;
}
protected:
// 初始化
bool Init(ImgSourceFactory *_imgSourceFactory);
// 在End中调用Close()
bool End();
// 运行 模板方法
virtual void Run(cv::Mat & _mat, std::vector<BndBox>& _vecBndBox) = 0;
private:
bool m_bRunState;
BaseImgSource * m_imgSource;
RecognitionYoloV3 * m_recYolo;
std::vector<BndBox> m_verNowRecResult;
};
#endif // !BASEOPERATION_H
BaseOperation.cpp
#pragma once
#include "BaseOperation.h"
void BaseOperation::Running(cv::Mat _mat)
{
cv::Mat _mat;
while (m_bRunState)
{
if (m_imgSource->GetMat(_mat))
{
if (m_recYolo->ImageDetect(_mat, m_verNowRecResult))
{
Run(_mat, m_verNowRecResult);
}
}
}
}
bool BaseOperation::Init(BaseImgSource * _imgSource)
{
m_imgSource = _imgSource;
m_recYolo = new RecognitionYoloV3();
return m_imgSource->Init();
}
bool BaseOperation::Init(ImgSourceFactory * _imgSourceFactory)
{
m_imgSource = _imgSourceFactory->CreateImgSource();
return true;
}
bool BaseOperation::End()
{
m_bRunState = false;
return m_imgSource->Close();
}
OperationSaveObjRect.h
#pragma once
#ifndef OPERATIONSAVEOBJRECT_H
#define OPERATIONSAVEOBJRECT_H
#include "BaseOperation.h"
#include "../Recognition/BndBox.h"
#include
class OperationSaveObjRect : public BaseOperation
{
public:
OperationSaveObjRect(std::string & _needSaveObjName, std::string &_needSaveFolderName)
:m_needSaveObjName(_needSaveObjName), m_needSaveFolderName(_needSaveFolderName)
{
}
protected:
// 运行
virtual void Run(cv::Mat & _mat, std::vector& _vecBndBox)
{
// 判断 _vecBndBox 中是否存在
for (auto _bndbox : _vecBndBox)
{
if (m_needSaveObjName == _bndbox->GetStrObjectName())
{
cv::Rect _rect = _bndbox->ToCvRect();
std::string _saveFilePath = m_needSaveFolderName + "/"+ m_needSaveObjName + std::to_string(size++);
_bndbox->SaveCvRect(_mat, _rect, )
}
}
}
private:
std::string m_needSaveObjName;
std::string m_needSaveFolderName;
int size = 0;
}
#endif // !OPERATIONSAVEOBJRECT_H