Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
cd981f4d
Commit
cd981f4d
authored
Apr 26, 2011
by
Maria Dimashova
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
started to integrate DOT detector
parent
0a8c7d27
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
1095 additions
and
0 deletions
+1095
-0
objdetect.hpp
modules/objdetect/include/opencv2/objdetect/objdetect.hpp
+106
-0
dotdetector.cpp
modules/objdetect/src/dotdetector.cpp
+855
-0
dot.cpp
samples/cpp/dot.cpp
+134
-0
No files found.
modules/objdetect/include/opencv2/objdetect/objdetect.hpp
View file @
cd981f4d
...
...
@@ -426,6 +426,8 @@ protected:
Ptr
<
CvHaarClassifierCascade
>
oldCascade
;
};
void
CV_EXPORTS_W
groupRectangles
(
vector
<
Rect
>&
rectList
,
int
groupThreshold
,
double
eps
,
vector
<
int
>*
weights
,
vector
<
double
>*
levelWeights
);
//////////////// HOG (Histogram-of-Oriented-Gradients) Descriptor and Object Detector //////////////
struct
CV_EXPORTS_W
HOGDescriptor
...
...
@@ -574,6 +576,110 @@ protected:
FernClassifier
fernClassifier
;
};
/****************************************************************************************\
* Dominant Orientation Templates *
\****************************************************************************************/
class
CV_EXPORTS
DOTDetector
{
public
:
struct
TrainParams
{
enum
{
BIN_COUNT
=
7
};
static
double
BIN_RANGE
()
{
return
180.0
/
BIN_COUNT
;
}
TrainParams
();
TrainParams
(
const
Size
&
winSize
,
int
regionSize
=
7
,
int
minMagnitude
=
60
,
int
maxStrongestCount
=
7
,
int
maxNonzeroBits
=
6
,
float
minRatio
=
0.85
f
);
void
read
(
FileNode
&
fn
);
void
write
(
FileStorage
&
fs
)
const
;
void
asserts
()
const
;
Size
winSize
;
int
regionSize
;
int
minMagnitude
;
int
maxStrongestCount
;
int
maxNonzeroBits
;
float
minRatio
;
};
struct
DetectParams
{
DetectParams
();
DetectParams
(
float
minRatio
,
int
minRegionSize
,
int
maxRegionSize
,
int
regionSizeStep
,
bool
isGroup
,
int
groupThreshold
,
double
groupEps
);
void
asserts
(
float
minTrainRatio
=
1.
f
)
const
;
float
minRatio
;
int
minRegionSize
;
int
maxRegionSize
;
int
regionSizeStep
;
bool
isGroup
;
int
groupThreshold
;
double
groupEps
;
};
struct
DOTTemplate
{
DOTTemplate
();
DOTTemplate
(
const
cv
::
Mat
&
quantizedImage
,
int
classID
,
const
cv
::
Mat
&
maskedImage
=
cv
::
Mat
(),
const
cv
::
Mat
&
gradientMask
=
cv
::
Mat
()
);
void
addClassID
(
int
classID
,
const
cv
::
Mat
&
maskedImage
=
cv
::
Mat
(),
const
cv
::
Mat
&
gradientMask
=
cv
::
Mat
()
);
static
float
computeTexturelessRatio
(
const
cv
::
Mat
&
quantizedImage
);
void
read
(
FileNode
&
fn
);
void
write
(
FileStorage
&
fs
)
const
;
cv
::
Mat
quantizedImage
;
std
::
vector
<
int
>
classIDs
;
float
texturelessRatio
;
std
::
vector
<
cv
::
Mat
>
maskedImages
;
std
::
vector
<
cv
::
Mat
>
gradientMasks
;
};
DOTDetector
();
DOTDetector
(
const
std
::
string
&
filename
);
// load from xml-file
virtual
~
DOTDetector
();
void
clear
();
void
read
(
FileNode
&
fn
);
void
write
(
FileStorage
&
fs
)
const
;
void
load
(
const
std
::
string
&
filename
);
void
save
(
const
std
::
string
&
filename
)
const
;
void
train
(
const
string
&
baseDirName
,
const
TrainParams
&
trainParams
=
TrainParams
(),
bool
isAddImageAndGradientMask
=
false
);
void
detectMultiScale
(
const
Mat
&
image
,
vector
<
vector
<
Rect
>
>&
rects
,
const
DetectParams
&
detectParams
=
DetectParams
(),
vector
<
vector
<
float
>
>*
ratios
=
0
,
vector
<
vector
<
int
>
>*
trainTemplateIndices
=
0
)
const
;
const
vector
<
DOTTemplate
>&
getDOTTemplates
()
const
;
const
vector
<
string
>&
getClassNames
()
const
;
static
void
groupRectanglesList
(
std
::
vector
<
std
::
vector
<
cv
::
Rect
>
>&
rectList
,
int
groupThreshold
,
double
eps
);
protected
:
void
detectQuantized
(
const
Mat
&
queryQuantizedImage
,
float
minRatio
,
vector
<
vector
<
Rect
>
>&
rects
,
vector
<
vector
<
float
>
>&
ratios
,
vector
<
vector
<
int
>
>&
trainTemlateIdxs
)
const
;
TrainParams
trainParams
;
bool
isAddImageAndGradientMask
;
std
::
vector
<
std
::
string
>
classNames
;
std
::
vector
<
DOTTemplate
>
dotTemplates
;
};
}
/****************************************************************************************\
...
...
modules/objdetect/src/dotdetector.cpp
0 → 100644
View file @
cd981f4d
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
#include <iostream>
#include <fstream>
using
namespace
std
;
namespace
cv
{
/*
* Functions
*/
static
void
readDirContent
(
const
string
&
descrFilename
,
vector
<
string
>&
names
)
{
names
.
clear
();
ifstream
file
(
descrFilename
.
c_str
()
);
if
(
!
file
.
is_open
()
)
return
;
while
(
!
file
.
eof
()
)
{
string
str
;
getline
(
file
,
str
);
if
(
str
.
empty
()
)
break
;
if
(
str
[
0
]
==
'#'
)
continue
;
// comment
names
.
push_back
(
str
);
}
file
.
close
();
}
static
void
computeGradients
(
const
Mat
&
image
,
Mat
&
magnitudes
,
Mat
&
angles
)
{
Mat
dx
,
dy
;
cv
::
Sobel
(
image
,
dx
,
CV_32F
,
1
,
0
,
3
);
cv
::
Sobel
(
image
,
dy
,
CV_32F
,
0
,
1
,
3
);
cv
::
cartToPolar
(
dx
,
dy
,
magnitudes
,
angles
,
true
);
CV_Assert
(
magnitudes
.
type
()
==
CV_32FC1
);
CV_Assert
(
angles
.
type
()
==
CV_32FC1
);
}
static
void
computeWinData
(
const
Mat
&
image
,
const
Mat
&
mask
,
const
Size
&
winSize
,
Mat
&
winImage
,
Mat
&
winMask
,
Mat
&
winMagnitudes
,
Mat
&
winAngles
,
int
border
=
0
)
{
CV_Assert
(
border
>=
0
);
Size
extSize
;
extSize
.
width
=
winSize
.
width
+
2
*
border
;
extSize
.
height
=
winSize
.
height
+
2
*
border
;
if
(
mask
.
empty
()
)
{
image
.
copyTo
(
winImage
);
winMask
.
release
();
}
else
{
vector
<
Point
>
points
;
points
.
reserve
(
image
.
rows
*
image
.
cols
);
for
(
int
y
=
0
;
y
<
mask
.
rows
;
y
++
)
{
for
(
int
x
=
0
;
x
<
mask
.
cols
;
x
++
)
{
if
(
mask
.
at
<
uchar
>
(
y
,
x
)
)
points
.
push_back
(
cv
::
Point
(
x
,
y
)
);
}
}
cv
::
Rect_
<
float
>
brect
=
cv
::
boundingRect
(
cv
::
Mat
(
points
)
);
float
ratio
=
std
::
min
(
(
float
)
winSize
.
width
/
brect
.
width
,
(
float
)
winSize
.
height
/
brect
.
height
);
float
rectWidth
=
winSize
.
width
/
ratio
;
float
rectHeight
=
winSize
.
height
/
ratio
;
float
scaledBorder
=
border
/
ratio
;
brect
.
x
-=
(
rectWidth
-
brect
.
width
)
/
2.
f
+
scaledBorder
;
brect
.
y
-=
(
rectHeight
-
brect
.
height
)
/
2.
f
+
scaledBorder
;
brect
.
width
=
rectWidth
+
2
*
scaledBorder
;
brect
.
height
=
rectHeight
+
2
*
scaledBorder
;
// TODO the following cases:
assert
(
Rect
(
0
,
0
,
image
.
cols
,
image
.
rows
).
contains
(
brect
.
tl
()
)
);
assert
(
Rect
(
0
,
0
,
image
.
cols
,
image
.
rows
).
contains
(
brect
.
br
()
)
);
Mat
subImage
(
image
,
brect
);
Mat
subMask
(
mask
,
brect
);
cv
::
resize
(
subImage
,
winImage
,
extSize
);
cv
::
resize
(
subMask
,
winMask
,
extSize
);
CV_Assert
(
winImage
.
size
()
==
extSize
);
CV_Assert
(
winMask
.
size
()
==
extSize
);
}
computeGradients
(
winImage
,
winMagnitudes
,
winAngles
);
// Mat bluredWinImage;
// cv::GaussianBlur( winImage, bluredWinImage, Size(), 0.5, 0.5 );
// computeGradients( bluredWinImage, magnitudes, angles );
}
inline
int
getBin
(
double
angle
)
{
double
angle1
=
angle
>=
180
?
angle
-
180
:
angle
;
int
orientationBin
=
(
int
)(
angle1
/
DOTDetector
::
TrainParams
::
BIN_RANGE
()
);
assert
(
orientationBin
<
7
);
return
orientationBin
;
}
static
void
copyTrainData
(
const
Mat
&
magnitudesSrc
,
const
Mat
&
anglesSrc
,
const
Mat
&
mask
,
Mat
&
magnitudesDst
,
Mat
&
anglesDst
)
{
magnitudesDst
=
Mat
(
magnitudesSrc
.
size
(),
magnitudesSrc
.
type
(),
Scalar
::
all
(
-
1
)
);
anglesDst
=
Mat
(
anglesSrc
.
size
(),
anglesSrc
.
type
(),
Scalar
::
all
(
-
1
)
);
magnitudesSrc
.
copyTo
(
magnitudesDst
,
mask
);
anglesSrc
.
copyTo
(
anglesDst
,
mask
);
}
inline
int
countNonZeroBits
(
uchar
val
)
{
uchar
v
=
val
;
v
=
(
v
&
0x55
)
+
((
v
>>
1
)
&
0x55
);
v
=
(
v
&
0x33
)
+
((
v
>>
2
)
&
0x33
);
return
(
v
&
0x0f
)
+
((
v
>>
4
)
&
0x0f
);
}
inline
void
countNonZeroAndTexturelessBits
(
const
Mat
&
mat
,
int
&
nonZeroBitsCount
,
int
&
texturelessBitsCount
)
{
CV_Assert
(
mat
.
type
()
==
CV_8UC1
);
nonZeroBitsCount
=
0
;
texturelessBitsCount
=
0
;
const
uchar
texturelessValue
=
1
<<
DOTDetector
::
TrainParams
::
BIN_COUNT
;
for
(
int
y
=
0
;
y
<
mat
.
rows
;
y
++
)
{
for
(
int
x
=
0
;
x
<
mat
.
cols
;
x
++
)
{
int
curCount
=
countNonZeroBits
(
mat
.
at
<
uchar
>
(
y
,
x
)
);
if
(
curCount
)
{
nonZeroBitsCount
+=
curCount
;
if
(
mat
.
at
<
uchar
>
(
y
,
x
)
==
texturelessValue
)
texturelessBitsCount
++
;
}
}
}
}
static
void
quantizeToTrain
(
const
Mat
&
_magnitudesExt
,
const
Mat
&
_anglesExt
,
const
Mat
&
maskExt
,
Mat
&
quantizedImage
,
const
DOTDetector
::
TrainParams
&
params
)
{
CV_DbgAssert
(
params
.
winSize
.
height
%
params
.
regionSize
==
0
);
CV_DbgAssert
(
params
.
winSize
.
width
%
params
.
regionSize
==
0
);
CV_DbgAssert
(
params
.
regionSize
%
2
==
1
);
const
int
regionSize_2
=
params
.
regionSize
/
2
;
Mat
magnitudesExt
,
anglesExt
;
copyTrainData
(
_magnitudesExt
,
_anglesExt
,
maskExt
,
magnitudesExt
,
anglesExt
);
const
int
verticalRegionCount
=
params
.
winSize
.
height
/
params
.
regionSize
;
const
int
horizontalRegionCount
=
params
.
winSize
.
width
/
params
.
regionSize
;
quantizedImage
=
Mat
(
verticalRegionCount
,
horizontalRegionCount
,
CV_8UC1
,
Scalar
::
all
(
0
)
);
Rect
curRect
(
regionSize_2
,
regionSize_2
,
params
.
regionSize
,
params
.
regionSize
);
for
(
int
vRegIdx
=
0
;
vRegIdx
<
verticalRegionCount
;
vRegIdx
++
)
{
for
(
int
hRegIdx
=
0
;
hRegIdx
<
horizontalRegionCount
;
hRegIdx
++
)
{
uchar
curRectBits
=
0
;
for
(
int
yShift
=
-
regionSize_2
;
yShift
<=
regionSize_2
;
yShift
++
)
// TODO yShift += regionSize/2
{
Rect
shiftedRect
=
curRect
;
shiftedRect
.
y
=
curRect
.
y
+
yShift
;
for
(
int
xShift
=
-
regionSize_2
;
xShift
<=
regionSize_2
;
xShift
++
)
// TODO xShift += regionSize/2
{
shiftedRect
.
x
=
curRect
.
x
+
xShift
;
Mat
subMagnitudes
(
magnitudesExt
,
shiftedRect
),
subMagnitudesCopy
;
subMagnitudes
.
copyTo
(
subMagnitudesCopy
);
Mat
subAngles
(
anglesExt
,
shiftedRect
);
double
maxMagnitude
;
int
strongestCount
=
0
;
for
(
;
strongestCount
<
params
.
maxStrongestCount
;
strongestCount
++
)
{
Point
maxLoc
;
cv
::
minMaxLoc
(
subMagnitudesCopy
,
0
,
&
maxMagnitude
,
0
,
&
maxLoc
);
if
(
maxMagnitude
<
params
.
minMagnitude
)
break
;
subMagnitudesCopy
.
at
<
float
>
(
maxLoc
)
=
-
1
;
double
angle
=
subAngles
.
at
<
float
>
(
maxLoc
);
int
orientationBin
=
getBin
(
angle
);
curRectBits
|=
1
<<
orientationBin
;
}
if
(
strongestCount
==
0
&&
maxMagnitude
>
0
)
curRectBits
|=
1
<<
DOTDetector
::
TrainParams
::
BIN_COUNT
;
}
}
if
(
!
(
curRectBits
==
(
1
<<
DOTDetector
::
TrainParams
::
BIN_COUNT
)
&&
cv
::
countNonZero
(
magnitudesExt
(
curRect
)
==
-
1
)
)
)
{
if
(
countNonZeroBits
(
curRectBits
)
<=
params
.
maxNonzeroBits
)
quantizedImage
.
at
<
uchar
>
(
vRegIdx
,
hRegIdx
)
=
curRectBits
;
}
curRect
.
x
+=
params
.
regionSize
;
}
curRect
.
x
=
regionSize_2
;
curRect
.
y
+=
params
.
regionSize
;
}
}
static
void
quantizeToDetect
(
const
Mat
&
_magnitudes
,
const
Mat
&
angles
,
Mat
&
quantizedImage
,
const
DOTDetector
::
TrainParams
&
params
)
{
Mat
magnitudes
;
_magnitudes
.
copyTo
(
magnitudes
);
const
int
verticalRegionCount
=
magnitudes
.
rows
/
params
.
regionSize
;
const
int
horizontalRegionCount
=
magnitudes
.
cols
/
params
.
regionSize
;
quantizedImage
=
Mat
(
verticalRegionCount
,
horizontalRegionCount
,
CV_8UC1
,
Scalar
::
all
(
0
)
);
Rect
curRect
(
0
,
0
,
params
.
regionSize
,
params
.
regionSize
);
const
int
maxStrongestCount
=
1
;
for
(
int
vRegIdx
=
0
;
vRegIdx
<
verticalRegionCount
;
vRegIdx
++
)
{
for
(
int
hRegIdx
=
0
;
hRegIdx
<
horizontalRegionCount
;
hRegIdx
++
)
{
uchar
curRectBits
=
0
;
Mat
subMagnitudes
(
magnitudes
,
curRect
),
subMagnitudesCopy
;
subMagnitudes
.
copyTo
(
subMagnitudesCopy
);
Mat
subAngles
(
angles
,
curRect
);
double
maxMagnitude
=
-
1
;
int
strongestCount
=
0
;
for
(
;
strongestCount
<
maxStrongestCount
;
strongestCount
++
)
{
Point
maxLoc
;
cv
::
minMaxLoc
(
subMagnitudesCopy
,
0
,
&
maxMagnitude
,
0
,
&
maxLoc
);
if
(
maxMagnitude
<
params
.
minMagnitude
)
break
;
subMagnitudesCopy
.
at
<
float
>
(
maxLoc
)
=
-
1
;
double
angle
=
subAngles
.
at
<
float
>
(
maxLoc
);
int
orientationBin
=
getBin
(
angle
);
curRectBits
|=
1
<<
orientationBin
;
}
if
(
strongestCount
==
0
&&
maxMagnitude
>
0
)
curRectBits
|=
1
<<
DOTDetector
::
TrainParams
::
BIN_COUNT
;
quantizedImage
.
at
<
uchar
>
(
vRegIdx
,
hRegIdx
)
=
curRectBits
;
curRect
.
x
+=
params
.
regionSize
;
}
curRect
.
x
=
0
;
curRect
.
y
+=
params
.
regionSize
;
}
}
inline
void
andQuantizedImages
(
const
Mat
&
queryQuantizedImage
,
const
Mat
&
trainQuantizedImage
,
float
&
ratio
,
float
&
texturelessRatio
)
{
int
nonZeroCount
=
0
,
texturelessCount
=
0
;
countNonZeroAndTexturelessBits
(
trainQuantizedImage
&
queryQuantizedImage
,
nonZeroCount
,
texturelessCount
);
CV_Assert
(
nonZeroCount
>
0
);
int
area
=
cv
::
countNonZero
(
trainQuantizedImage
);
ratio
=
(
float
)
nonZeroCount
/
area
;
texturelessRatio
=
texturelessCount
/
nonZeroCount
;
}
static
void
computeTrainUsedStrongestMask
(
const
Mat
&
_magnitudesExt
,
const
Mat
&
_anglesExt
,
const
Mat
&
maskExt
,
const
Mat
&
quantizedImage
,
Mat
&
winUsedStrongestMask
,
int
regionSize
,
int
minMagnitude
)
{
const
int
usedLabel
=
255
;
const
int
regionSize_2
=
regionSize
/
2
;
Mat
magnitudesExt
,
anglesExt
;
copyTrainData
(
_magnitudesExt
,
_anglesExt
,
maskExt
,
magnitudesExt
,
anglesExt
);
const
int
verticalRegionCount
=
quantizedImage
.
rows
;
const
int
horizontalRegionCount
=
quantizedImage
.
cols
;
Mat
binsExt
(
anglesExt
.
size
(),
CV_32SC1
,
Scalar
::
all
(
-
1
)
);
for
(
int
y
=
0
;
y
<
binsExt
.
rows
;
y
++
)
{
for
(
int
x
=
0
;
x
<
binsExt
.
cols
;
x
++
)
{
if
(
magnitudesExt
.
at
<
float
>
(
y
,
x
)
>=
minMagnitude
)
{
binsExt
.
at
<
int
>
(
y
,
x
)
=
getBin
(
anglesExt
.
at
<
float
>
(
y
,
x
)
);
}
}
}
Rect
curRect
(
0
,
0
,
regionSize
+
2
*
regionSize_2
,
regionSize
+
2
*
regionSize_2
);
Mat
colorsExt
(
anglesExt
.
size
(),
CV_8UC1
,
Scalar
::
all
(
0
)
);
for
(
int
vRegIdx
=
0
;
vRegIdx
<
verticalRegionCount
;
vRegIdx
++
)
{
for
(
int
hRegIdx
=
0
;
hRegIdx
<
horizontalRegionCount
;
hRegIdx
++
)
{
Mat
subColors
=
colorsExt
(
curRect
);
Mat
subBins
=
binsExt
(
curRect
);
uchar
bits
=
quantizedImage
.
at
<
uchar
>
(
vRegIdx
,
hRegIdx
);
for
(
int
binIdx
=
0
;
binIdx
<
DOTDetector
::
TrainParams
::
BIN_COUNT
;
binIdx
++
)
{
if
(
bits
&
(
1
<<
binIdx
)
)
{
float
gray
=
usedLabel
/* * weights[vRegIdx*horizontalRegionCount+hRegIdx][binIdx]*/
;
subColors
.
setTo
(
Scalar
((
uchar
)
cvRound
(
gray
)),
subBins
==
binIdx
);
}
}
curRect
.
x
+=
regionSize
;
}
curRect
.
x
=
0
;
curRect
.
y
+=
regionSize
;
}
Mat
colors
=
colorsExt
(
Rect
(
regionSize_2
,
regionSize_2
,
binsExt
.
cols
-
2
*
regionSize_2
,
binsExt
.
rows
-
2
*
regionSize_2
)
);
colors
.
convertTo
(
winUsedStrongestMask
,
CV_8UC1
);
}
/*
* DOTDetector::Params
*/
DOTDetector
::
TrainParams
::
TrainParams
()
:
winSize
(
Size
(
84
,
84
)),
regionSize
(
7
),
minMagnitude
(
60
),
maxStrongestCount
(
7
),
maxNonzeroBits
(
6
),
minRatio
(
0.85
f
)
{}
DOTDetector
::
TrainParams
::
TrainParams
(
const
Size
&
_winSize
,
int
_regionSize
,
int
_minMagnitude
,
int
_maxStrongestCount
,
int
_maxNonzeroBits
,
float
_minRatio
)
:
winSize
(
_winSize
),
regionSize
(
_regionSize
),
minMagnitude
(
_minMagnitude
),
maxStrongestCount
(
_maxStrongestCount
),
maxNonzeroBits
(
_maxNonzeroBits
),
minRatio
(
_minRatio
)
{
asserts
();
}
void
DOTDetector
::
TrainParams
::
asserts
()
const
{
CV_Assert
(
winSize
.
width
>
0
&&
winSize
.
height
>
0
);
CV_Assert
(
regionSize
>
0
&&
regionSize
%
2
==
1
);
CV_Assert
(
winSize
.
width
%
regionSize
==
0
);
CV_Assert
(
winSize
.
height
%
regionSize
==
0
);
CV_Assert
(
minMagnitude
>
0
);
CV_Assert
(
maxStrongestCount
>
0
&&
maxStrongestCount
<=
BIN_COUNT
);
CV_Assert
(
maxNonzeroBits
>
0
&&
maxNonzeroBits
<=
BIN_COUNT
);
CV_Assert
(
minRatio
>
0.
f
&&
minRatio
<
1.
f
);
}
void
DOTDetector
::
TrainParams
::
read
(
FileNode
&
fn
)
{
winSize
.
width
=
fn
[
"winSize.width"
];
winSize
.
height
=
fn
[
"winSize.height"
];
regionSize
=
fn
[
"regionSize"
];
minMagnitude
=
fn
[
"minMagnitude"
];
maxStrongestCount
=
fn
[
"maxStrongestCount"
];
maxNonzeroBits
=
fn
[
"maxNonzeroBits"
];
minRatio
=
fn
[
"minRatio"
];
asserts
();
}
void
DOTDetector
::
TrainParams
::
write
(
FileStorage
&
fs
)
const
{
CV_Assert
(
fs
.
isOpened
()
);
fs
<<
"winSize.width"
<<
winSize
.
width
;
fs
<<
"winSize.height"
<<
winSize
.
height
;
fs
<<
"regionSize"
<<
regionSize
;
fs
<<
"minMagnitude"
<<
minMagnitude
;
fs
<<
"maxStrongestCount"
<<
maxStrongestCount
;
fs
<<
"maxNonzeroBits"
<<
maxNonzeroBits
;
fs
<<
"minRatio"
<<
minRatio
;
}
DOTDetector
::
DetectParams
::
DetectParams
()
:
minRatio
(
0.8
f
),
minRegionSize
(
7
),
maxRegionSize
(
9
),
regionSizeStep
(
2
),
isGroup
(
true
),
groupThreshold
(
3
),
groupEps
(
0.2
)
{}
DOTDetector
::
DetectParams
::
DetectParams
(
float
_minRatio
,
int
_minRegionSize
,
int
_maxRegionSize
,
int
_regionSizeStep
,
bool
_isGroup
,
int
_groupThreshold
,
double
_groupEps
)
:
minRatio
(
_minRatio
),
minRegionSize
(
_minRegionSize
),
maxRegionSize
(
_maxRegionSize
),
regionSizeStep
(
_regionSizeStep
),
isGroup
(
_isGroup
),
groupThreshold
(
_groupThreshold
),
groupEps
(
_groupEps
)
{
asserts
();
}
void
DOTDetector
::
DetectParams
::
asserts
(
float
minTrainRatio
)
const
{
CV_Assert
(
minRatio
>
0
&&
minRatio
<
1
);
CV_Assert
(
minRatio
<=
minTrainRatio
);
CV_Assert
(
minRegionSize
>
0
&&
minRegionSize
%
2
==
1
);
CV_Assert
(
maxRegionSize
>
0
&&
maxRegionSize
%
2
==
1
);
CV_Assert
(
minRegionSize
<=
maxRegionSize
);
CV_Assert
(
regionSizeStep
%
2
==
0
);
if
(
isGroup
)
{
CV_Assert
(
groupThreshold
>
0
);
CV_Assert
(
groupEps
>
0
&&
groupEps
<
1
);
}
}
/*
* DOTDetector::DOTTemplate
*/
DOTDetector
::
DOTTemplate
::
DOTTemplate
()
:
texturelessRatio
(
-
1.
f
)
{}
DOTDetector
::
DOTTemplate
::
DOTTemplate
(
const
cv
::
Mat
&
_quantizedImage
,
int
_classID
,
const
cv
::
Mat
&
_maskedImage
,
const
cv
::
Mat
&
_gradientMask
)
:
quantizedImage
(
_quantizedImage
),
texturelessRatio
(
computeTexturelessRatio
(
_quantizedImage
))
{
addClassID
(
_classID
,
_maskedImage
,
_gradientMask
);
}
void
DOTDetector
::
DOTTemplate
::
addClassID
(
int
_classID
,
const
cv
::
Mat
&
_maskedImage
,
const
cv
::
Mat
&
_gradientMask
)
{
CV_Assert
(
_classID
>=
0
);
bool
isFound
=
false
;
for
(
size_t
i
=
0
;
i
<
classIDs
.
size
();
i
++
)
{
if
(
classIDs
[
i
]
==
_classID
)
{
isFound
=
true
;
break
;
}
}
if
(
!
isFound
)
{
classIDs
.
push_back
(
_classID
);
if
(
!
_maskedImage
.
empty
()
)
{
CV_Assert
(
!
_gradientMask
.
empty
()
);
maskedImages
.
push_back
(
_maskedImage
);
gradientMasks
.
push_back
(
_gradientMask
);
}
}
}
float
DOTDetector
::
DOTTemplate
::
computeTexturelessRatio
(
const
cv
::
Mat
&
quantizedImage
)
{
const
uchar
TEXTURELESS_VAL
=
1
<<
DOTDetector
::
TrainParams
::
BIN_COUNT
;
int
texturelessCount
=
0
;
for
(
int
y
=
0
;
y
<
quantizedImage
.
rows
;
y
++
)
{
for
(
int
x
=
0
;
x
<
quantizedImage
.
cols
;
x
++
)
{
if
(
quantizedImage
.
at
<
uchar
>
(
y
,
x
)
&
TEXTURELESS_VAL
)
texturelessCount
++
;
}
}
return
(
float
)
texturelessCount
/
(
float
)(
quantizedImage
.
cols
*
quantizedImage
.
rows
);
}
void
DOTDetector
::
DOTTemplate
::
read
(
FileNode
&
fn
)
{
fn
[
"template"
]
>>
quantizedImage
;
fn
[
"classIDs"
]
>>
classIDs
;
texturelessRatio
=
fn
[
"texturelessRatio"
];
}
void
DOTDetector
::
DOTTemplate
::
write
(
FileStorage
&
fs
)
const
{
fs
<<
"template"
<<
quantizedImage
;
fs
<<
"classIDs"
<<
classIDs
;
fs
<<
"texturelessRatio"
<<
texturelessRatio
;
}
/*
* DOTDetector
*/
DOTDetector
::
DOTDetector
()
:
isAddImageAndGradientMask
(
false
)
{
}
DOTDetector
::
DOTDetector
(
const
std
::
string
&
filename
)
:
isAddImageAndGradientMask
(
false
)
{
load
(
filename
);
}
DOTDetector
::~
DOTDetector
()
{
clear
();
}
void
DOTDetector
::
clear
()
{
classNames
.
clear
();
dotTemplates
.
clear
();
}
void
DOTDetector
::
read
(
FileNode
&
fn
)
{
clear
();
// read params
FileNode
fn_params
=
fn
[
"train_params"
];
trainParams
.
read
(
fn_params
);
// read class names
int
classCount
=
fn
[
"class_count"
];
FileNodeIterator
fni
=
fn
[
"class_names"
].
begin
();
for
(
int
i
=
0
;
i
<
classCount
;
i
++
)
{
string
name
;
fni
>>
name
;
classNames
.
push_back
(
name
);
}
// read DOT templates
int
templatesCount
=
fn
[
"templates_count"
];
fni
=
fn
[
"templates"
].
begin
();
for
(
int
i
=
0
;
i
<
templatesCount
;
i
++
)
{
dotTemplates
.
push_back
(
DOTTemplate
()
);
FileNode
cur_fn
=
*
fni
;
dotTemplates
.
rbegin
()
->
read
(
cur_fn
);
}
}
void
DOTDetector
::
write
(
FileStorage
&
fs
)
const
{
// write params
fs
<<
"train_params"
<<
"{"
;
trainParams
.
write
(
fs
);
fs
<<
"}"
;
//params
// write class names
fs
<<
"class_count"
<<
(
int
)
classNames
.
size
();
fs
<<
"class_names"
<<
"["
;
for
(
size_t
i
=
0
;
i
<
classNames
.
size
();
i
++
)
{
fs
<<
classNames
[
i
];
}
fs
<<
"]"
;
// write dot templates
fs
<<
"templates_count"
<<
(
int
)
dotTemplates
.
size
();
fs
<<
"templates"
<<
"["
;
for
(
size_t
i
=
0
;
i
<
dotTemplates
.
size
();
i
++
)
{
dotTemplates
[
i
].
write
(
fs
);
}
fs
<<
"]"
;
}
void
DOTDetector
::
load
(
const
std
::
string
&
filename
)
{
FileStorage
fs
(
filename
,
FileStorage
::
READ
);
if
(
fs
.
isOpened
()
)
{
FileNode
fn
=
fs
.
getFirstTopLevelNode
();
read
(
fn
);
}
}
void
DOTDetector
::
save
(
const
std
::
string
&
filename
)
const
{
FileStorage
fs
(
filename
,
FileStorage
::
WRITE
);
if
(
fs
.
isOpened
()
)
{
fs
<<
"dot_detector"
<<
"{"
;
write
(
fs
);
fs
<<
"}"
;
}
}
void
DOTDetector
::
train
(
const
string
&
_baseDirName
,
const
TrainParams
&
_trainParams
,
bool
_isAddImageAndGradientMask
)
{
clear
();
trainParams
=
_trainParams
;
trainParams
.
asserts
();
string
baseDirName
=
_baseDirName
+
(
*
(
_baseDirName
.
end
()
-
1
)
==
'/'
?
""
:
"/"
);
const
int
regionSize_2
=
trainParams
.
regionSize
/
2
;
readDirContent
(
baseDirName
+
"objects.txt"
,
classNames
);
for
(
size_t
objIdx
=
0
;
objIdx
<
classNames
.
size
();
objIdx
++
)
{
string
curObjDirName
=
baseDirName
+
classNames
[
objIdx
]
+
"/"
;
cout
<<
"==============="
<<
classNames
[
objIdx
]
<<
"==============="
<<
endl
;
vector
<
string
>
imagesFilenames
;
readDirContent
(
curObjDirName
+
"images.txt"
,
imagesFilenames
);
if
(
imagesFilenames
.
empty
()
)
continue
;
int
countSamples
=
0
;
for
(
size_t
imgIdx
=
0
;
imgIdx
<
imagesFilenames
.
size
();
imgIdx
++
)
{
cout
<<
imagesFilenames
[
imgIdx
]
;
Mat
image
=
cv
::
imread
(
curObjDirName
+
imagesFilenames
[
imgIdx
],
0
);
if
(
image
.
empty
()
)
continue
;
Mat
mask
;
{
Mat
_mask
=
cv
::
imread
(
curObjDirName
+
imagesFilenames
[
imgIdx
]
+
".mask.png"
,
0
);
if
(
_mask
.
empty
()
)
{
cout
<<
" - FAIL"
<<
endl
;
continue
;
}
mask
=
_mask
;
}
cout
<<
" - OK"
<<
endl
;
countSamples
++
;
Mat
trainImageExt
,
trainMaskExt
,
trainQuantizedImage
,
detectQuantizedImage
;
Mat
trainMagnitudesExt
,
trainAnglesExt
;
computeWinData
(
image
,
mask
,
trainParams
.
winSize
,
trainImageExt
,
trainMaskExt
,
trainMagnitudesExt
,
trainAnglesExt
,
regionSize_2
);
quantizeToTrain
(
trainMagnitudesExt
,
trainAnglesExt
,
trainMaskExt
,
trainQuantizedImage
,
trainParams
);
quantizeToDetect
(
trainMagnitudesExt
,
trainAnglesExt
,
detectQuantizedImage
,
trainParams
);
vector
<
vector
<
Rect
>
>
rects
;
vector
<
vector
<
float
>
>
ratios
;
vector
<
vector
<
int
>
>
trainTemplatesIdxs
;
detectQuantized
(
detectQuantizedImage
,
trainParams
.
minRatio
,
rects
,
ratios
,
trainTemplatesIdxs
);
Mat
maskedTrainImage
,
trainGradientMask
;
if
(
isAddImageAndGradientMask
)
{
trainImageExt
.
copyTo
(
maskedTrainImage
,
trainMaskExt
);
computeTrainUsedStrongestMask
(
trainMagnitudesExt
,
trainAnglesExt
,
trainMaskExt
,
trainQuantizedImage
,
trainGradientMask
,
trainParams
.
regionSize
,
trainParams
.
minMagnitude
);
}
int
classID
=
classNames
.
size
()
-
1
;
bool
isFound
=
false
;
for
(
size_t
cIdx
=
0
;
cIdx
<
trainTemplatesIdxs
.
size
();
cIdx
++
)
{
if
(
trainTemplatesIdxs
[
cIdx
].
size
()
)
{
for
(
size_t
i
=
0
;
i
<
trainTemplatesIdxs
[
cIdx
].
size
();
i
++
)
{
int
tIdx
=
trainTemplatesIdxs
[
cIdx
][
i
];
dotTemplates
[
tIdx
].
addClassID
(
classID
,
maskedTrainImage
,
trainGradientMask
);
isFound
=
true
;
}
}
}
if
(
!
isFound
)
{
dotTemplates
.
push_back
(
DOTTemplate
(
trainQuantizedImage
,
classID
,
maskedTrainImage
,
trainGradientMask
)
);
}
cout
<<
"dot templates size = "
<<
dotTemplates
.
size
()
<<
endl
;
}
}
}
void
DOTDetector
::
detectQuantized
(
const
Mat
&
testQuantizedImage
,
float
minRatio
,
vector
<
vector
<
Rect
>
>&
rects
,
vector
<
vector
<
float
>
>&
ratios
,
vector
<
vector
<
int
>
>&
trainTemlateIdxs
)
const
{
if
(
dotTemplates
.
empty
()
)
return
;
const
int
regionsPerRow
=
dotTemplates
[
0
].
quantizedImage
.
rows
;
const
int
regionsPerCol
=
dotTemplates
[
0
].
quantizedImage
.
cols
;
int
classCount
=
classNames
.
size
();
rects
.
resize
(
classCount
);
ratios
.
resize
(
classCount
);
trainTemlateIdxs
.
resize
(
classCount
);
for
(
size_t
tIdx
=
0
;
tIdx
<
dotTemplates
.
size
();
tIdx
++
)
{
Rect
r
(
0
,
0
,
regionsPerCol
,
regionsPerRow
);
for
(
r
.
y
=
0
;
r
.
y
<=
testQuantizedImage
.
rows
-
r
.
height
;
r
.
y
++
)
{
for
(
r
.
x
=
0
;
r
.
x
<=
testQuantizedImage
.
cols
-
r
.
width
;
r
.
x
++
)
{
float
ratio
,
texturelessRatio
;
andQuantizedImages
(
testQuantizedImage
(
r
),
dotTemplates
[
tIdx
].
quantizedImage
,
ratio
,
texturelessRatio
);
if
(
ratio
>
minRatio
&&
texturelessRatio
<
dotTemplates
[
tIdx
].
texturelessRatio
)
{
for
(
size_t
cIdx
=
0
;
cIdx
<
dotTemplates
[
tIdx
].
classIDs
.
size
();
cIdx
++
)
{
int
classID
=
dotTemplates
[
tIdx
].
classIDs
[
cIdx
];
rects
[
classID
].
push_back
(
r
);
ratios
[
classID
].
push_back
(
ratio
);
trainTemlateIdxs
[
classID
].
push_back
(
tIdx
);
}
}
}
}
}
}
void
DOTDetector
::
detectMultiScale
(
const
Mat
&
image
,
vector
<
vector
<
Rect
>
>&
rects
,
const
DetectParams
&
detectParams
,
vector
<
vector
<
float
>
>*
ratios
,
vector
<
vector
<
int
>
>*
trainTemplateIndices
)
const
{
detectParams
.
asserts
(
trainParams
.
minRatio
);
int
classCount
=
classNames
.
size
();
rects
.
resize
(
classCount
);
if
(
ratios
)
{
ratios
->
clear
();
if
(
!
detectParams
.
isGroup
)
ratios
->
resize
(
classCount
);
}
if
(
trainTemplateIndices
)
{
trainTemplateIndices
->
clear
();
if
(
!
detectParams
.
isGroup
)
trainTemplateIndices
->
resize
(
classCount
);
}
Mat
magnitudes
,
angles
;
computeGradients
(
image
,
magnitudes
,
angles
);
for
(
int
regionSize
=
detectParams
.
minRegionSize
;
regionSize
<=
detectParams
.
maxRegionSize
;
regionSize
+=
detectParams
.
regionSizeStep
)
{
Mat
quantizedImage
;
vector
<
vector
<
Rect
>
>
curRects
;
vector
<
vector
<
float
>
>
curRatios
;
vector
<
vector
<
int
>
>
curTrainTemlateIdxs
;
quantizeToDetect
(
magnitudes
,
angles
,
quantizedImage
,
trainParams
);
detectQuantized
(
quantizedImage
,
detectParams
.
minRatio
,
curRects
,
curRatios
,
curTrainTemlateIdxs
);
for
(
int
ci
=
0
;
ci
<
classCount
;
ci
++
)
{
for
(
size_t
ri
=
0
;
ri
<
curRects
[
ci
].
size
();
ri
++
)
{
Rect
r
=
curRects
[
ci
][
ri
];
r
.
x
*=
regionSize
;
r
.
y
*=
regionSize
;
r
.
width
*=
regionSize
;
r
.
height
*=
regionSize
;
rects
[
ci
].
push_back
(
r
);
if
(
ratios
&&
!
detectParams
.
isGroup
)
(
*
ratios
)[
ci
].
push_back
(
curRatios
[
ci
][
ri
]
);
if
(
trainTemplateIndices
&&
!
detectParams
.
isGroup
)
(
*
trainTemplateIndices
)[
ci
].
push_back
(
curTrainTemlateIdxs
[
ci
][
ri
]
);
}
}
}
if
(
detectParams
.
isGroup
)
groupRectanglesList
(
rects
,
detectParams
.
groupThreshold
,
detectParams
.
groupEps
);
}
const
vector
<
DOTDetector
::
DOTTemplate
>&
DOTDetector
::
getDOTTemplates
()
const
{
return
dotTemplates
;
}
const
vector
<
string
>&
DOTDetector
::
getClassNames
()
const
{
return
classNames
;
}
void
DOTDetector
::
groupRectanglesList
(
std
::
vector
<
std
::
vector
<
cv
::
Rect
>
>&
rectList
,
int
groupThreshold
,
double
eps
)
{
for
(
size_t
i
=
0
;
i
<
rectList
.
size
();
i
++
)
groupRectangles
(
rectList
[
i
],
groupThreshold
,
eps
);
}
}
// namespace cv
/* End of file. */
samples/cpp/dot.cpp
0 → 100644
View file @
cd981f4d
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <iostream>
#include <fstream>
using
namespace
cv
;
using
namespace
std
;
#define SHOW_ALL_RECTS_BY_ONE 1
static
void
fillColors
(
vector
<
Scalar
>&
colors
)
{
cv
::
RNG
rng
=
theRNG
();
for
(
size_t
ci
=
0
;
ci
<
colors
.
size
();
ci
++
)
colors
[
ci
]
=
Scalar
(
rng
(
256
),
rng
(
256
),
rng
(
256
)
);
}
static
void
readTestImageNames
(
const
string
&
descrFilename
,
vector
<
string
>&
names
)
{
names
.
clear
();
ifstream
file
(
descrFilename
.
c_str
()
);
if
(
!
file
.
is_open
()
)
return
;
while
(
!
file
.
eof
()
)
{
string
str
;
getline
(
file
,
str
);
if
(
str
.
empty
()
)
break
;
if
(
str
[
0
]
==
'#'
)
continue
;
// comment
names
.
push_back
(
str
);
}
file
.
close
();
}
int
main
(
int
argc
,
char
**
argv
)
{
if
(
argc
!=
1
&&
argc
!=
3
)
{
cout
<<
"Format: base; "
<<
endl
<<
"or without arguments to use default data"
<<
endl
;
return
-
1
;
}
string
baseDirName
,
testDirName
;
if
(
argc
==
1
)
{
baseDirName
=
"../MultiScaleDOT/Data/train/"
;
testDirName
=
"../MultiScaleDOT/Data/test/"
;
}
else
{
baseDirName
=
argv
[
1
];
testDirName
=
argv
[
2
];
baseDirName
+=
(
*
(
baseDirName
.
end
()
-
1
)
==
'/'
?
""
:
"/"
);
testDirName
+=
(
*
(
testDirName
.
end
()
-
1
)
==
'/'
?
""
:
"/"
);
}
DOTDetector
::
TrainParams
trainParams
;
trainParams
.
winSize
=
Size
(
84
,
84
);
trainParams
.
regionSize
=
7
;
trainParams
.
minMagnitude
=
60
;
// we ignore pixels with magnitude less then minMagnitude
trainParams
.
maxStrongestCount
=
7
;
// we find such count of strongest gradients for each region
trainParams
.
maxNonzeroBits
=
6
;
// we filter very textured regions (that have more then maxUnzeroBits count of 1s (ones) in the template)
trainParams
.
minRatio
=
0.85
f
;
// 1. Train detector
DOTDetector
dotDetector
;
dotDetector
.
train
(
baseDirName
,
trainParams
,
true
);
const
vector
<
string
>&
classNames
=
dotDetector
.
getClassNames
();
const
vector
<
DOTDetector
::
DOTTemplate
>&
dotTemplates
=
dotDetector
.
getDOTTemplates
();
vector
<
Scalar
>
colors
(
classNames
.
size
()
);
fillColors
(
colors
);
cout
<<
"Templates count "
<<
dotTemplates
.
size
()
<<
endl
;
vector
<
string
>
testFilenames
;
readTestImageNames
(
testDirName
+
"images.txt"
,
testFilenames
);
if
(
testFilenames
.
empty
()
)
{
cout
<<
"Can not read no one test images"
<<
endl
;
return
-
1
;
}
// 2. Detect objects
DOTDetector
::
DetectParams
detectParams
;
detectParams
.
minRatio
=
0.8
f
;
detectParams
.
minRegionSize
=
5
;
detectParams
.
maxRegionSize
=
11
;
#if SHOW_ALL_RECTS_BY_ONE
detectParams
.
isGroup
=
false
;
#endif
for
(
size_t
imgIdx
=
0
;
imgIdx
<
testFilenames
.
size
();
imgIdx
++
)
{
string
curFilename
=
testDirName
+
testFilenames
[
imgIdx
];
cout
<<
curFilename
<<
endl
;
Mat
queryImage
=
imread
(
curFilename
,
0
);
if
(
queryImage
.
empty
()
)
continue
;
cout
<<
"Detection start ..."
<<
endl
;
vector
<
vector
<
Rect
>
>
rects
;
vector
<
vector
<
float
>
>
ratios
;
vector
<
vector
<
int
>
>
trainTemlateIdxs
;
dotDetector
.
detectMultiScale
(
queryImage
,
rects
,
detectParams
,
&
ratios
,
&
trainTemlateIdxs
);
cout
<<
"end"
<<
endl
;
Mat
draw
;
cvtColor
(
queryImage
,
draw
,
CV_GRAY2BGR
);
#if SHOW_ALL_RECTS_BY_ONE
DOTDetector
::
groupRectanglesList
(
rects
,
3
,
0.2
);
#endif
const
int
textStep
=
25
;
for
(
size_t
ci
=
0
;
ci
<
classNames
.
size
();
ci
++
)
{
putText
(
draw
,
classNames
[
ci
],
Point
(
textStep
,
textStep
*
(
1
+
ci
)),
1
,
2
,
colors
[
ci
],
3
);
for
(
size_t
ri
=
0
;
ri
<
rects
[
ci
].
size
();
ri
++
)
{
rectangle
(
draw
,
rects
[
ci
][
ri
],
colors
[
ci
],
3
);
}
}
Mat
scaledDraw
;
cv
::
resize
(
draw
,
scaledDraw
,
Size
(
640
,
480
)
);
imshow
(
"detection result"
,
scaledDraw
);
cv
::
waitKey
();
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment