-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathellipse_detect.h
242 lines (193 loc) · 9.08 KB
/
ellipse_detect.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
#ifndef ELLIPSE_DETECT
#define ELLIPSE_DETECT
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include "opencv2/core/utility.hpp"
//#include <opencv2/bgsegm.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/video/background_segm.hpp>
#include <queue>
#include <config.h>
//fwd declaration of vector of DetectedEllispods
//class tEllipsoids;
class tDetectedEllipsoid; //Fwd decl
typedef std::vector<tDetectedEllipsoid> tEllipsoids;
typedef std::priority_queue<tDetectedEllipsoid> tRankQueueEllipsoids;
///\note Consistency between pts and RotRect is not checked
typedef struct tDetectedEllipsoid{
tDetectedEllipsoid():rectEllipse()
{
fitscore = 0;
cLabel = 'N'; //Not set / Default value
ptAxisMj1.x = 0;
ptAxisMj1.y = 0;
ptAxisMj2.x = 0;
ptAxisMj2.y = 0;
nsamples = 1;
}
//Constructor for instantiating an average Ellipsoid using the N ellipsoids from Queue
tDetectedEllipsoid(tRankQueueEllipsoids& rankedEllipsoids,int nMaxSamples):tDetectedEllipsoid()
{
int iRSamples =rankedEllipsoids.size();//Total Samples
nsamples = 0; //Samples included in Estimate
tDetectedEllipsoid ellipsoid;
tEllipsoids vellipses;
fitscore = 0;
while (rankedEllipsoids.size() > max(0,iRSamples-nMaxSamples))
{
ellipsoid = rankedEllipsoids.top();
if (ellipsoid.ptAxisMj1.y > ellipsoid.ptAxisMj2.y)
{ //ptAxisMj1 is lower than ptAxisMj2
ptAxisMj1.y += ellipsoid.ptAxisMj1.y ;
ptAxisMj1.x += ellipsoid.ptAxisMj1.x ;
ptAxisMj2.y += ellipsoid.ptAxisMj2.y ;
ptAxisMj2.x += ellipsoid.ptAxisMj2.x ;
}
else
{
ptAxisMj1.y += ellipsoid.ptAxisMj2.y;
ptAxisMj1.x += ellipsoid.ptAxisMj2.x;
ptAxisMj2.y += ellipsoid.ptAxisMj1.y;
ptAxisMj2.x += ellipsoid.ptAxisMj1.x;
}
fitscore += ellipsoid.fitscore;
rankedEllipsoids.pop();
nsamples++;
}//Loop Through TOp Ranking Ellipsoids
//Calc empirical mean /
ptAxisMj1.y = ptAxisMj1.y / (float)nsamples;
ptAxisMj1.x = ptAxisMj1.x / (float)nsamples;
ptAxisMj2.y = ptAxisMj2.y / (float)nsamples;
ptAxisMj2.x = ptAxisMj2.x / (float)nsamples;
if (nsamples > 0)
fitscore = fitscore/ (float)nsamples;
else
fitscore = 0;
cv::Point2f mjAxisLine = ptAxisMj2-ptAxisMj1;
/// \todo set the other bounding rect points accordingly
this->rectEllipse.angle = std::atan2(mjAxisLine.y,mjAxisLine.x) * 180.0/CV_PI+90.0;
}//Constuctor With Rank Q
//Initialiazes object using mean values from vector of ellipsoids provided
tDetectedEllipsoid(const tEllipsoids& vEll):tDetectedEllipsoid()
{
//Iterate all ellipsoids and obtain mean values
//Note as position of MjAxis pt1 pt2 is not consistently lower/ upper
// we need to avg in a directional way so the means are consistent for lower/upper point
nsamples = vEll.size();
for (int i=0;i<vEll.size();i++)
{
tDetectedEllipsoid rEll = vEll[i];
//nsamples += rEll.nsamples;
if (rEll.ptAxisMj1.y > rEll.ptAxisMj2.y)
{ //ptAxisMj1 is lower than ptAxisMj2
ptAxisMj1.y += rEll.ptAxisMj1.y ;
ptAxisMj1.x += rEll.ptAxisMj1.x ;
ptAxisMj2.y += rEll.ptAxisMj2.y ;
ptAxisMj2.x += rEll.ptAxisMj2.x ;
}
else
{
ptAxisMj1.y += rEll.ptAxisMj2.y;
ptAxisMj1.x += rEll.ptAxisMj2.x;
ptAxisMj2.y += rEll.ptAxisMj1.y;
ptAxisMj2.x += rEll.ptAxisMj1.x;
}
fitscore += rEll.fitscore;
} //lOOP through all ellipsoids
//Calc empirical mean /
ptAxisMj1.y = ptAxisMj1.y / (float)nsamples;
ptAxisMj1.x = ptAxisMj1.x / (float)nsamples;
ptAxisMj2.y = ptAxisMj2.y / (float)nsamples;
ptAxisMj2.x = ptAxisMj2.x / (float)nsamples;
fitscore = fitscore/ (float)nsamples;
cv::Point2f mjAxisLine = ptAxisMj2-ptAxisMj1;
/// \todo set the other bounding rect points accordingly
this->rectEllipse.angle = std::atan2(mjAxisLine.y,mjAxisLine.x) * 180.0/CV_PI+90.0;
}
//cv::RotatedRect(ptxy0,cv::Size2f(2*a,2*idx), alpha*(180/M_PI))
/// \todo recalc all rect points / not just angle
tDetectedEllipsoid(cv::Point2f pt0,cv::Point2f pt1,cv::Point2f pt2,int score,cv::RotatedRect r):rectEllipse(r)
{
if (pt1.y < pt2.y) //set so ptMj1 is the lower image point of the ellipse
{ //Pt1 is above pt2
ptAxisMj1 = pt2; //Major Axis Point 1;
ptAxisMj2 = pt1; //Major Axis Point 2;
}
else
{//Pt1 is below pt2
ptAxisMj1 = pt1; //Major Axis Point 1;
ptAxisMj2 = pt2; //Major Axis Point 2;
}
fitscore = score;
cv::Point2f mjAxisLine = ptAxisMj2-ptAxisMj1;
r.angle = std::atan2(mjAxisLine.y,mjAxisLine.x) * 180.0/M_PI+90.0;
}
tDetectedEllipsoid(cv::RotatedRect r,int score):rectEllipse(r){
if (r.angle >= 90)
rectEllipse.angle = r.angle-180.0;
if (r.angle <= -90)
rectEllipse.angle = 180.0+r.angle;
fitscore = score;
ptAxisMj1.x = r.center.x + r.size.height*sin(-r.angle*M_PI/180.0)/3.0;
ptAxisMj1.y = r.center.y + r.size.height*cos(-r.angle*M_PI/180.0)/3.0;
ptAxisMj2.x = r.center.x - r.size.height*sin(-r.angle*M_PI/180.0)/3.0;
ptAxisMj2.y = r.center.y - r.size.height*cos(-r.angle*M_PI/180.0)/3.0;
//cv::Point2f ptBoxPts[4];
//r.points(ptBoxPts);
//ptAxisMj1 = r.center + (ptBoxPts[0]-(cv::Point2f)r.center)+(ptBoxPts[1]-ptBoxPts[0])/2.0;
//ptAxisMj2 = r.center + (ptBoxPts[2]-(cv::Point2f)r.center); //+(ptBoxPts[2]-ptBoxPts[3])/2.0;
}
//Operator for Priority Ordering
// bool operator<(const tDetectedEllipsoid& b) {
// return this->fitscore < b.fitscore; //Max Heap
// }
cv::RotatedRect rectEllipse;
int fitscore;
int nsamples = 0;
cv::Point2f ptAxisMj1;
cv::Point2f ptAxisMj2;
float stdDev;
char cLabel; ///A label char used to distinguish sets of detect ellipses (ie left right Eye here )
//Returns corrected angle as used for reporting eye angles
float getEyeAngle()
{
//float fEyeTheta;
//fEyeTheta = rectEllipse.angle;
// if (fEyeTheta > 90)
// fEyeTheta = rectEllipse.angle-90;
// if (fEyeTheta < -30)
// fEyeTheta = rectEllipse.angle+90;
if (!isnan(rectEllipse.angle) )
return (rectEllipse.angle);
else
return (std::numeric_limits<double>::quiet_NaN());
}
} tDetectedEllipsoid;
//Operator for Priority Ordering
bool operator<(const tDetectedEllipsoid& a,const tDetectedEllipsoid& b);
typedef struct tEllipsoidEdge {
tEllipsoidEdge(cv::Point2f pt):ptEdge(pt) {}
cv::Point2f ptEdge;
int minorAxisLength;
} tEllipsoidEdge;
typedef std::vector<tEllipsoidEdge> tEllipsoidEdges;
//int detectEllipses(cv::Mat& imgIn,cv::Mat& imgOut,tEllipsoids& vellipses);
//int detectEllipses(cv::Mat& imgIn,cv::Mat& imgOut,int angleDeg,tEllipsoids& vellipses);
int detectEllipse(cv::Mat& imgEdgeIn,tEllipsoidEdges& vedgePoints_all, tRankQueueEllipsoids& qEllipsoids);
///
/// \brief detectEllipses Search For Ellipsoids around the position of the eyes in the fish head isolated image
int detectEyeEllipses(cv::Mat& pimgIn,tEllipsoids& vLellipses,tEllipsoids& vRellipses,cv::Mat& outHeadFrameMonitor,cv::Mat& outHeadFrameProc);
// Uses Sampling around an arc below the eyes to determine Appropriate Eye Segmentation theshold (Max N values are used)
//int getEyeSegThreshold(cv::Mat& pimgIn,cv::Point2f ptcenter,std::vector<cv::Point>& ellipseSample_pts);
std::vector<int> getEyeSegThreshold(cv::Mat& pimgIn,cv::Point2f ptcenter,std::vector<cv::Point>& ellipseSample_pts,int& minVal,int& maxVal);
void getEdgePoints(cv::Mat& imgEdgeIn,tEllipsoidEdges& vedgepoint);
void getEdgePoints(std::vector<cv::Point>& contour,tEllipsoidEdges& vedgepoint);
/// Functions for optimizing ellipse detection to only consider connected pairs of points (ie points that belong to the same line/curve
void getEdgePoints(std::vector<cv::Point>& contour,tEllipsoidEdges& vedgepoint);/// Fills A list with point coords where pixels (edges image) are above a threshold (non-zero)
void getPointsAlongEdge(cv::Mat imgEdgeIn,cv::Point2f startpt,tEllipsoidEdges& vedgepoint);
void getConnectedEdgePoints(cv::Mat& imgEdgeIn,cv::Point2f startpt,tEllipsoidEdges& vedgepoint);
void getBestEllipsoidFits(cv::Mat& imgRegion,tRankQueueEllipsoids& qEllipsoids,cv::Point ptLoc,cv::Point ptLocBottom);
void show_histogram(std::string const& name, cv::Mat1b const& image);
/// Draws LInes On Upsampled Head Image showing the major axis of ellipses
float drawExtendedMajorAxis(cv::Mat& outHeadFrameMonitor,tDetectedEllipsoid& ellEye,cv::Scalar col);
#endif // ELLIPSE_DETECT