You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
wheeldetect/3part/Cyclops/include/Luffy.h

335 lines
12 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#ifndef _Luffy_Process_h_
#define _Luffy_Process_h_
#include "CVUtils.h"
#include "stdio.h"
#include <list>
#include <map>
using namespace cv;
using std::vector;
namespace luffy_base
{
#define LP_MAX_ANGLE 360
#define LP_GRAY_LEVEL 256
#define LP_MAX_GRAY_VALUE 255
#define LP_COLOR_GREEN Scalar(0, 255, 0)
#define LP_COLOR_RED Scalar(0, 0, 255)
#define LP_COLOR_BLUE Scalar(255, 0, 0)
#define LP_COLOR_WHITE Scalar(255, 255, 255)
#define LP_COLOR_BLACK Scalar(0, 0, 0)
#define LuffyMax(a, b) ((a)>(b) ? (a) : (b))
#define LuffyMin(a, b) ((a)<(b) ? (a) : (b))
#define LP_SINGLE_LINE 1
class luffyCircle
{
public:
luffyCircle() :ptCenter(0,0), fRadius(0){}
public:
Point2f ptCenter;
float fRadius;
};
class luffyObject
{
public:
luffyObject();
Rect rtPos;
float getRadius() { return (rtPos.width / 2.0); }
//Rect
};
typedef int LP_NORM_METHOD;
class luffyPos
{
public:
Point m_ptInPic; //圆在大图中的圆心位置
Point m_ptInROI; //圆在ROI中的圆心位置
Rect m_rtROI; //ROI区域
float m_fRadiusAvg; //半径
};
/*
阈值分割算法汇总
emThresMethodDefault 按照param1作为阈值分割
emThresMethodInv 按照param1作为阈值
emThresMethodRatio 按照灰度总数的前百分比emThresMethodRatio计算值作为阈值
emThresMethodNum 按照灰度总数的前emThresMethodNum个灰度数量作为阈值
emThresMethodOtsu 最大间方差得到的阈值
emThresMethodIteration 迭代法
emThresMethodBasicGlobal 基本全局阈值法
emThresMethodMaxEntropy 最大熵阈值分割
emThresMethodHuangFuzzy
*/
namespace luffy_threshold {
enum EmThresMethod {
emThresMethodDefault = 000, emThresMethodInv = 100, emThresMethodRatio = 2, emThresMethodNum = 3, emThresMethodOtsu = 4,
emThresMethodIteration= 5, emThresMethodBasicGlobal = 6, emThresMethodMaxEntropy = 7, emThresMethodHuangFuzzy = 8, emThresMethod2 = 9
};
void calcuHist(const Mat &src, Mat &matHist, int &nTotal, Mat &mask = gDummyMat);
int getThresValue(Mat &matHist, int nTotal, double dRatio, EmThresMethod emMethod = emThresMethodRatio);
int Threshold(const Mat &src, Mat &dst, double param1, int nThresMethod = emThresMethodDefault, Mat mask = Mat());
int Threshold(const Mat &src, Mat &dst, vector<double> param, int nThresMethod = emThresMethodDefault, Mat mask = Mat());
}
/*
投影计数:直角坐标与极坐标投影
*/
namespace luffy_projection {
enum EmProjectionDirect { emProjX = 0, emProjY = 1 };
void project2point(const Mat & src, Mat & projDst, Point ptCenter, int nAngleCount, LP_NORM_METHOD normType = 0);
void project2axis(const Mat & src, Mat & projDst, EmProjectionDirect param1 = emProjX, LP_NORM_METHOD normType = 0);
}
//<! 基本的图像处理方法
namespace luffy_imageProc {
void meanvarnorm(Mat& src, Mat &dst, double avg, double var, Mat mask = Mat()); //<! 此函数由大饼提供
bool lsCircleFit(vector<Point> &points, float &fRadius, Point2f &center); //<! 最小二乘法圆拟合
bool lsLineFit(vector<Point> &points, float& a, float &b); //<! 最小二乘法直线拟合 y = a + b * x
void rotateImage(Mat &src, Mat &dst, float angle, Point ptCenter = Point(), int clockWise = 1);
void RemoveSmallRegion(Mat &Src, Mat &Dst, int AreaLimit, int CheckMode, int NeihborMode);
int judgeCircle(const vector<Point> &vec, Point2f ptCenter, float radius, float dDiff);
enum EmCreateMode{
emCreateDefault, emCreateGray, emCreateColor, emCreateCopy, emCreateNull
};
void createImage(Mat & src, Mat & dst, EmCreateMode emMode = emCreateDefault, Scalar color = Scalar::all(0));
void sobel(Mat &src, Mat *pDst = NULL, Mat *pSobelX = NULL, Mat *pSobelY = NULL, int iBlockSize = 3);
enum EmGradientMethod {
emGradient1
};
void ComputeGradient(Mat & src, EmGradientMethod method = emGradient1, Mat *pAngle = nullptr, Mat *pMag = NULL);
//<! fit model by Ransac
enum EmModel {
emModelCircle, emModelLine
};
struct RansacParam {
RansacParam(float fProb, float fErrorDis, int nMaxItCount, int nMinFitNum, int nBreakCondit) {
m_fProb = fProb; m_fErrorDis = fErrorDis; m_nMinFitNum = nMinFitNum; m_nMaxItCount = nMaxItCount; m_nBreakCondit = nBreakCondit;
}
float m_fProb;
float m_fErrorDis;
int m_nMaxItCount;
int m_nMinFitNum;
int m_nBreakCondit;
};
vector<Point> genRandPoints(vector<Point> & vecPoints, float fProb, int prec = 100);
vector <Point> fitModelbyRansac(vector<Point> &vecPoints, EmModel emModel, float fProb, float errorDis, int nMaxItNum, int minFitNum, int breakCondi);
vector <Point> fitModelbyRansac(vector<Point> &vecPoints, EmModel emModel, RansacParam *pParam);
bool fitModel(vector<Point> &vecPoints, vector<double> &vecRes, EmModel emModel);
}
/*
数学类操作:几何+代数
*/
namespace luffy_math {
int mod(int index, int total, int periodNum = 1); //<! 取余
float getVectorsAngle(float angle1, float angle2, const int nMaxAngle = 360); //<! 求夹角中心
float caculAngle(Point ptCenter, Point ptTarget); //<! 角度计算
template<typename T1, typename T2> //<! 点之间距离
float disofPoints(T1 pt1, T2 pt2) {
float dx = pt1.x - pt2.x;
float dy = pt1.y - pt2.y;
return (float)sqrtf(dx*dx + dy*dy);
}
template <typename T>
float disofPoint2Line(T pt, float a, float b) { //<! 点与直线间的距离, y=a+bx
return fabs(pt.x * b + a - pt.y) / sqrtf(a*a + b*b);
}
template<typename T>
bool sort2Data(T &minData, T &maxData) { //<! 2数据排序
if (minData <= maxData) return true;
else {
T tmp = minData; minData = maxData; maxData = tmp;
return false;
}
};
bool isOutRange(Point pt, Size size);
bool checkPoint(Point &pt, Rect rt);
bool checkData(int &nData, int nMax, int nMin);
bool checkRoiRect(Size imgSize, Rect & rtRoi);
bool checkSquare(Rect rect, int nMinWidth, int nMaxWidth, int nMaxDiff = 20);
bool checkSquare(RotatedRect rect, float nMinWidth, float nMaxWidth, float nMaxDiff = 20);
bool checkSquare(Size2f size, float nMinWidth, float nMaxWidth, float nMaxDiff = 20);
void LeastSquare1d(const cv::Mat & mat1d, cv::Mat &Basemat, cv::Mat &Residualmat);
double rotateRectIntersects(const cv::RotatedRect &rRect1, const cv::RotatedRect& rRect2, bool ifDis = true);
enum EmDataMinMax{ emDataMax, emDataMin };
double getMinMaxData(const Mat & src, EmDataMinMax emData = emDataMax, Point *pIndex = NULL);
Point polar2rect(Point2f ptCenter, float radius, float dCos, float dSin);
void polar2rect(const Mat &src, Mat &dst, Point ptCenter, int nRadiusIn, int nRadiusOut, int nAngleMax);
}
bool CheckMatEqu(const cv::Mat &mask1, const cv::Mat &mask2, bool ifcheckType=false);
bool CheckMatLogical(const cv::Mat &src);
//<! 一位数组数据可视化
void drawCurveUsingArray(const Mat &src, Mat &dst, LP_NORM_METHOD normType = 0, Scalar bgColor = Scalar::all(255), Scalar curveColor = Scalar::all(0));
//<! 大小端
void swapBigEndian(unsigned short &data);
/*
图像匹配
1、图像模板匹配广义上的图像不单单指灰度图本身
2、轮廓线匹配
*/
namespace luffy_match {
enum EmLoopMatchDirect { emLoopMatchCol = 0, emLoopMatX = 0, emLoopMatchRow = 1, emLoopMatY = 1 };
bool LoopMatMatch(Mat & src, Mat &temp, EmLoopMatchDirect direct, Mat &result, int method = CV_TM_CCORR_NORMED);
void LoopMatShift(Mat & src, Mat & dst, EmLoopMatchDirect direct, int clockwiseShift = 0); //<! 顺时针偏移 偏移量为clockwiseShift
}
/*
blob分析
0906可以取每一取blob的像素面积个数
*/
namespace luffy_blob {
struct PolyEdge{
PolyEdge() : y0(0), y1(0), x(0), dx(0), next(0) {}
int y0, y1;
int x, dx;
PolyEdge *next;
};
static const int CodeDeltas[8][2] =
{ { 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, 1 }, { 1, 1 } };
struct CmpEdges
{
bool operator ()(const PolyEdge& e1, const PolyEdge& e2)
{
return e1.y0 - e2.y0 ? e1.y0 < e2.y0 :
e1.x - e2.x ? e1.x < e2.x : e1.dx < e2.dx;
}
};
enum { XY_SHIFT = 16, XY_ONE = 1 << XY_SHIFT, DRAWING_STORAGE_BLOCK = (1 << 12) - 256 };
//20150906 当前版本只能计算每个blob的面积
//获取面积
//std::list<int> getArea(Size imgSize, vector< vector<Point> > &contours);
int getArea(const Size imgSize, const vector<Point> & contours);
//获取长度
std::list<int> getLeng(Size imgSize, vector< vector<Point> > contours, int contourIdx);
std::list<int> cvProcessContours(Size imgSize, CvSeq* contour, int max_level);
void CollectPolyEdges(const Point* v, int count, vector<PolyEdge>& edges, int shift);
int CaculCollectionArea(Size imgSize, vector<PolyEdge>& edges);
}
/*
三角函数值的快速索引
1、先初始化createNewTrigValue其中total表示将360°进行total份等分
2、创建完成之后即可使用getCos/Sin与getCosPtr/SinPtr索引相关参数index为total等分下的索引
*/
namespace luffy_triangle {
bool createNewTrigValue(int total);
bool releaseTrigValue(int total);
double getCos(int total, int index);
double getSin(int total, int index);
double *getCosPtr(int total);
double *getSinPtr(int total);
}
/*
碰击计算:记录从起点到终点,第一次遇见白点时候的坐标,分为极坐标与直角坐标
*/
namespace luffy_hit {
enum EmHitDirectParam {
emHitIn2Out = 0, emHitOut2In = 1,
emHitUp2Down = 0, emHitDown2Up = 1,
emHitLeft2Right = 2, emRight2Left = 3
};
class MoutainClamp {
public:
MoutainClamp(int iTotal = 360, bool bLoop = false) {
left = 0; right = 0; total = iTotal; m_bLoop = bLoop;
}
int left;
int right;
int total;
bool m_bLoop;
int getLen() {
return (m_bLoop == false) ? (right - left + 1) : luffy_math::mod(right - left + 1, total);
}
vector<Rect> getRect(int nRow, int nCols) {
vector<Rect> vecRect;
if (1 != nCols) {
if (left <= right) {
vecRect.push_back(Rect(left, 0, getLen(), LP_SINGLE_LINE));
}
else {
vecRect.push_back(Rect(left, 0, nCols - left + 1, LP_SINGLE_LINE));
vecRect.push_back(Rect(0, 0, right, LP_SINGLE_LINE));
}
}
else {
if (left <= right) {
vecRect.push_back(Rect(0, left, LP_SINGLE_LINE, getLen()));
}
else {
vecRect.push_back(Rect(0, left, LP_SINGLE_LINE, nRow - left + 1));
vecRect.push_back(Rect(0, 0, LP_SINGLE_LINE, right));
}
}
return vecRect;
};
double getSum(Mat & src){
double dSum = 0.0;
vector<Rect> vecRect = getRect(src.rows, src.cols);
for (int i = 0; i < vecRect.size(); i++) {
dSum += cv::sum(src(vecRect[i]))[0];
}
return dSum;
};
int getMid(){
return luffy_math::getVectorsAngle(left, right, total);
}
bool judgeLen(int nMin = 0, int nMax = 360, bool bLoop = false) {
int nLen = getLen();
return luffy_math::checkData(nLen, nMax, nMin);
}
};
void firstHit4Circle(Mat &binary, Mat &hit, vector<Point> &vecHit, Point ptCenter, int nIn, int nOut, int nHitCount = 360, EmHitDirectParam emHit = emHitOut2In);
void firstHit4Axis(Mat &binary, Mat &hit, int nMin, int nMax, EmHitDirectParam emHit = emHitUp2Down);
void hit2Moutain(Mat & src, std::vector<MoutainClamp> &vecMouts, float thresValue, int nWidth);
void filterMoutain(std::vector<MoutainClamp> & vecMouts, int nTotal, int minSpace, int minWidth, bool bLoop = false);
MoutainClamp getMaxWidthMoutain(std::vector<MoutainClamp> & vecMouts, bool bLoop = false);
MoutainClamp getMaxDensityMoutain(Mat &src, std::vector<MoutainClamp> & vecMouts, bool bLoop = false);
}
}
#endif //_Luffy_Process_h_