9 #include "BlobDetectorDOM.hh"
10 #include <Base/ImageUtils/ImageDraw.hh>
15 template <
class StorageType>
18 diffThreshold_ = 20.0;
25 maximumBinPopulation_ = 7;
26 similarityThreshold_ = 3;
27 intImg_ = (
double*)NULL;
30 template <
class StorageType>
32 if (intImg_ != NULL)
delete[] intImg_;
35 template <
class StorageType>
39 CreateIntegralImage(image);
42 generatedBlobs_.resize(0);
43 blobQualityVec_.resize(0);
46 if (blobs.size() == 0){
48 GenerateAndOptimize(generatedBlobs_,blobQualityVec_);
50 refineBlobPosAndSize(image);
52 for (
unsigned int i = 0; i < generatedBlobs_.size(); i++){
53 if (blobQualityVec_[i] >= diffThreshold_ && minBlobSize_ <= generatedBlobs_[i][2] && maxBlobSize_ >= generatedBlobs_[i][2]){
55 blob.
UL[0] = generatedBlobs_[i][0] - generatedBlobs_[i][2];
56 blob.
UL[1] = generatedBlobs_[i][1] - generatedBlobs_[i][2];
57 blob.
LR[0] = generatedBlobs_[i][0] + generatedBlobs_[i][2];
58 blob.
LR[1] = generatedBlobs_[i][1] + generatedBlobs_[i][2];
61 blob.
weight = (
unsigned int) blobQualityVec_[i];
62 blobs.push_back(blob);
70 template <
class StorageType>
73 for (
unsigned int i = 0; i < generatedBlobs_.size(); i++)
81 template <
class StorageType>
83 diffThreshold_ = threshold;
86 template <
class StorageType>
88 numberOfBins_ = cabinsPerAxis;
89 maximumBinPopulation_ = maxPopulation;
92 template <
class StorageType>
95 minBlobSize_ = minSize / 2;
98 template <
class StorageType>
101 maxBlobSize_ = maxSize / 2;
104 template <
class StorageType>
106 unsigned int maxSeedSize,
107 unsigned int seedSizeStep){
109 minSeedSize_ = minSeedSize / 2;
110 maxSeedSize_ = maxSeedSize / 2;
111 seedSizeStep_ = seedSizeStep / 2;
115 template <
class StorageType>
118 blobs = generatedBlobs_;
119 qual_vec = blobQualityVec_;
123 template <
class StorageType>
127 for (
int blobSeedSize = minSeedSize_; (
unsigned int)blobSeedSize <= maxSeedSize_; blobSeedSize += (int)seedSizeStep_){
130 for (
int x = blobSeedSize; x < (int)width_ - (
int)blobSeedSize; x += (int)blobSeedSize)
131 for (
int y = blobSeedSize; y < (int)width_ -(
int)blobSeedSize; y += (int)blobSeedSize){
134 HomgPoint2D blob = GetLocalMaximum(x,y, blobSeedSize);
135 float qual = GetDOM((
int)blob[0], (
int)blob[1], (
int)blob[2]);
138 if (qual > diffThreshold_ && blob[2] < maxBlobSize_){
139 int size = pos_vec.size();
142 unsigned int regionPopulation = 0;
143 unsigned int worstInRegion = 0;
144 float worstValueInRegion = FLT_MAX;
146 for (
int s = 0; s < size; s++){
147 if (fabs(pos_vec[s][0] - blob[0]) < ((
float)width_/(
float)numberOfBins_) &&
148 fabs(pos_vec[s][1] - blob[1]) < ((
float)height_/(
float)numberOfBins_)){
149 if (fabs(pos_vec[s][0] - blob[0]) < similarityThreshold_ &&
150 fabs(pos_vec[s][1] - blob[1]) < similarityThreshold_ &&
151 fabs(pos_vec[s][2] - blob[2]) < similarityThreshold_){
155 if ((
float)qual > qual_vec[s]){
157 qual_vec[s] = (float)qual;
161 if (qual_vec[s] <= worstValueInRegion){
162 worstValueInRegion = (float)qual_vec[s];
170 if (regionPopulation < maximumBinPopulation_){
172 pos_vec.push_back(blob);
173 qual_vec.push_back(qual);
175 if (worstValueInRegion <= qual){
178 qual_vec[worstInRegion] = qual;
179 pos_vec[worstInRegion] = blob;
190 template <
class StorageType>
195 for (
int i = 0; i < (int)generatedBlobs_.size(); i++){
198 int x = (int)generatedBlobs_[i][0];
199 int y = (int)generatedBlobs_[i][1];
200 int halfLevelSize = (int)generatedBlobs_[i][2];
203 double innerValueSum = EvalIntegralImage(x-halfLevelSize,y-halfLevelSize,x+halfLevelSize+1,y+halfLevelSize+1);
204 double completeValueSum = EvalIntegralImage(x-(halfLevelSize*2),y-(halfLevelSize*2),x+(halfLevelSize*2)+1,y+(halfLevelSize*2)+1);\
205 double outerValueSum = completeValueSum - innerValueSum;
206 double numOfInnerElements = (halfLevelSize*2+1)*(halfLevelSize*2+1);
207 double numOfOuterElements = (halfLevelSize*4+1)*(halfLevelSize*4+1) - numOfInnerElements;
210 double DOMValue = ((innerValueSum/numOfInnerElements) - (outerValueSum/numOfOuterElements));
211 bool positiveBlob = ((innerValueSum/numOfInnerElements) > (outerValueSum/numOfOuterElements));
213 float weightSum = 0.0;
214 generatedBlobs_[i][0] = 0.0;
215 generatedBlobs_[i][1] = 0.0;
216 generatedBlobs_[i][2] = 0.0;
219 for (
int xSearch = x-halfLevelSize; xSearch < x+halfLevelSize+1; xSearch++)
220 for (
int ySearch = y-halfLevelSize; ySearch < y+halfLevelSize+1; ySearch++){
221 if ((positiveBlob && (
float)ida[ySearch][numChannels*xSearch] >= (outerValueSum/numOfOuterElements))||
222 (!positiveBlob && (
float)ida[ySearch][numChannels*xSearch] <= (outerValueSum/numOfOuterElements))) {
224 if ((
float)ida[ySearch][numChannels*xSearch] >= (innerValueSum/numOfInnerElements) ||
225 (!positiveBlob && (
float)ida[ySearch][numChannels*xSearch] <= (innerValueSum/numOfInnerElements))){
226 generatedBlobs_[i][0] += (float)xSearch;
227 generatedBlobs_[i][1] += (float)ySearch;
230 float weight = fabs(((
float)ida[ySearch][numChannels*xSearch] -
float(outerValueSum/numOfOuterElements))
232 generatedBlobs_[i][0] += (float)xSearch * weight;
233 generatedBlobs_[i][1] += (float)ySearch * weight;
240 generatedBlobs_[i][0] /= (float)weightSum;
241 generatedBlobs_[i][1] /= (float)weightSum;
243 for (
int xSearch = x-halfLevelSize; xSearch < x+halfLevelSize+1; xSearch++)
244 for (
int ySearch = y-halfLevelSize; ySearch < y+halfLevelSize+1; ySearch++){
245 if ((positiveBlob && (
float)ida[ySearch][numChannels*xSearch] >= (outerValueSum/numOfOuterElements))||
246 (!positiveBlob && (float)ida[ySearch][numChannels*xSearch] <= (outerValueSum/numOfOuterElements))) {
247 float xDiff = (float)xSearch - (
float)generatedBlobs_[i][0];
248 float yDiff = (float)ySearch - (
float)generatedBlobs_[i][1];
249 float dist = sqrt(xDiff*xDiff+yDiff*yDiff);
250 float weight = fabs(((
float)ida[ySearch][numChannels*xSearch] - (
float)(outerValueSum/numOfOuterElements))
252 generatedBlobs_[i][2] += dist*weight;
256 generatedBlobs_[i][2] /=weightSum;
262 template <
class StorageType>
267 pos[2] = halfLevelSize;
268 float currentDOMVal = 0.0;
269 float newDOMVal = GetDOM((
int)pos[0], (
int)pos[1], (
int)pos[2]);
273 while(currentDOMVal < newDOMVal){
274 currentDOMVal = newDOMVal;
275 float bestDOMVal = newDOMVal;
278 for (
int x_step = -1; x_step <= 1; x_step++){
279 for (
int y_step = -1; y_step <= 1; y_step++){
280 for (
int l_step = -1; l_step <= 1; l_step++){
282 float DOMVal = GetDOM((
int)pos[0]+x_step, (
int)pos[1]+y_step, (
int)pos[2]+l_step);
283 if (DOMVal > bestDOMVal){
293 newDOMVal = bestDOMVal;
294 pos[0] = pos[0]+bestx_step;
295 pos[1] = pos[1]+besty_step;
296 pos[2] = pos[2]+bestl_step;
297 if (pos[2] < 3 || pos[2] > 30)
return pos;
303 template <
class StorageType>
307 if (x - halfLevelSize*2 < 0 || y - halfLevelSize*2 < 0 || x + halfLevelSize*2 +1 >= (
int)width_ || y + halfLevelSize*2 +1>= (
int)height_)
311 double innerValueSum = EvalIntegralImage(x-halfLevelSize,y-halfLevelSize,x+halfLevelSize+1,y+halfLevelSize+1);
313 double completeValueSum = EvalIntegralImage(x-(halfLevelSize*2),y-(halfLevelSize*2),x+(halfLevelSize*2)+1,y+(halfLevelSize*2)+1);\
315 double outerValueSum = completeValueSum - innerValueSum;
317 double numOfInnerElements = (halfLevelSize*2+1)*(halfLevelSize*2+1);
318 double numOfOuterElements = (halfLevelSize*4+1)*(halfLevelSize*4+1) - numOfInnerElements;
320 double DOMValue = fabs((innerValueSum/numOfInnerElements) - (outerValueSum/numOfOuterElements));
322 return (
float)DOMValue;
325 template <
class StorageType>
329 if (x - halfLevelSize*2 < 0 || y - halfLevelSize*2 < 0 || x + halfLevelSize*2 +1 >= (
int)width_ || y + halfLevelSize*2 +1>= (
int)height_)
333 double innerValueSum = EvalIntegralImage(x-halfLevelSize,y-halfLevelSize,x+halfLevelSize+1,y+halfLevelSize+1);
335 double completeValueSum = EvalIntegralImage(x-(halfLevelSize*2),y-(halfLevelSize*2),x+(halfLevelSize*2)+1,y+(halfLevelSize*2)+1);\
337 double outerValueSum = completeValueSum - innerValueSum;
339 double numOfInnerElements = (halfLevelSize*2+1)*(halfLevelSize*2+1);
340 double numOfOuterElements = (halfLevelSize*4+1)*(halfLevelSize*4+1) - numOfInnerElements;
342 return float((innerValueSum/numOfInnerElements) - (outerValueSum/numOfOuterElements));
351 template <
class StorageType>
354 if (intImg_ != NULL)
delete[]intImg_;
360 intImg_ =
new double[width_*height_];
363 intImg_[0] = (double)idaIn[0][0];
365 for (
unsigned int x=1; x < width_; x++)
366 intImg_[x] = (
double)idaIn[0][x]+intImg_[x-1];
368 for (
unsigned int y=1; y < height_; y++)
369 intImg_[y*width_] = (
double)idaIn[y][0]+intImg_[(y-1)*width_];
371 for (
unsigned int y=1; y < height_; y++)
372 for (
unsigned int x=1; x < width_; x++)
373 intImg_[y*width_+x] = (
double)idaIn[y][x*channels]+intImg_[(y-1)*width_+x]
374 +intImg_[y*width_+(x-1)] - intImg_[(y-1)*width_+(x-1)];
378 template <
class StorageType>
380 return (intImg_[yB*width_+xB] - intImg_[yB*width_+xA] - intImg_[yA*width_+xB] + intImg_[yA*width_+xA]);
389 #ifdef BUILD_IMAGE_INT
392 #ifdef BUILD_IMAGE_CHAR
395 #ifdef BUILD_IMAGE_SHORT
397 #ifdef BUILD_IMAGE_USHORT
400 #ifdef BUILD_IMAGE_UINT
402 #ifdef BUILD_IMAGE_DOUBLE
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
BIAS::Vector2< double > LR
unsigned int GetWidth() const
Helper class to store blob corners.
BIAS::Vector2< double > centerofmass
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
unsigned int GetHeight() const
The image template class for specific storage types.
BIAS::Vector2< double > UL
Blob detector for 'Difference Of Means'-blobs (so this is not a binary blob detector).
drawing simple entities into the image like rectangles or lines As all functions are static they have...
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase