Skip to content

Commit 123e03b

Browse files
committed
implement aggregated saliency optimization framework
1 parent 6f5d019 commit 123e03b

File tree

2 files changed

+83
-6
lines changed

2 files changed

+83
-6
lines changed

modules/saliency/include/opencv2/saliency/saliencySpecializedClasses.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,8 @@ class CV_EXPORTS_W BackgroundContrast : public StaticSaliency
217217
return false;
218218
return computeSaliencyImpl( image, saliencyMap );
219219
}
220-
Mat saliencyMapGenerator( const Mat );
220+
Mat saliencyMapGenerator( const Mat, const Mat = Mat(), int = 0 );
221+
void saliencyOptimize( const Mat, const Mat, const Mat, const Mat, Mat&, double = 14, double = 5 );
221222
Mat saliencyMapVisualize( InputArray _saliencyMap, int = 0 );
222223
protected:
223224
bool computeSaliencyImpl( InputArray image, OutputArray saliencyMap );

modules/saliency/src/BackgroundContrast.cpp

Lines changed: 81 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ BackgroundContrast::BackgroundContrast()
3939
}
4040
BackgroundContrast::~BackgroundContrast(){};
4141

42-
Mat BackgroundContrast::saliencyMapGenerator( const Mat img )
42+
Mat BackgroundContrast::saliencyMapGenerator( const Mat img, const Mat fgImg, int option )
4343
{
4444
Mat idxImg, adjcMatrix, colDistM, posDistM, bdProb, wCtr, saliency;
4545
superpixelSplit(img, idxImg, adjcMatrix);
@@ -54,7 +54,31 @@ Mat BackgroundContrast::saliencyMapGenerator( const Mat img )
5454
}
5555
getColorPosDis(img, idxImg, colDistM, posDistM, adjcMatrix.size[0]);
5656
boundaryConnectivity(adjcMatrix, colDistM, bdProb, bdIds);
57-
getWeightedContrast(colDistM, posDistM, bdProb, wCtr);
57+
58+
if ( option == 0 )
59+
{
60+
getWeightedContrast(colDistM, posDistM, bdProb, wCtr);
61+
62+
}
63+
else
64+
{
65+
Mat temp = fgImg.clone();
66+
resize(temp, temp, img.size());
67+
vector<int> szOfSP = vector<int>(adjcMatrix.size[0], 0);
68+
for ( int i = 0; i < img.size[0]; i++ )
69+
{
70+
for ( int j = 0; j < img.size[1]; j++ )
71+
{
72+
szOfSP[idxImg.at<unsigned>(i, j)]++;
73+
wCtr.at<double>(idxImg.at<unsigned>(i, j), 0) += temp.at<double>(i, j);
74+
}
75+
}
76+
for ( unsigned i = 0; i < szOfSP.size(); i++ )
77+
{
78+
wCtr.at<double>(i, 0) /= szOfSP[i];
79+
}
80+
}
81+
saliencyOptimize(adjcMatrix, colDistM, bdProb, wCtr, wCtr);
5882
saliency = Mat(img.size[0], img.size[1], CV_64F, Scalar::all(0.0));
5983
for (int i = 0; i < img.size[0]; i++)
6084
{
@@ -64,7 +88,59 @@ Mat BackgroundContrast::saliencyMapGenerator( const Mat img )
6488
}
6589
}
6690
return saliency;
67-
return img;
91+
}
92+
93+
void BackgroundContrast::saliencyOptimize( const Mat adjcMatrix, const Mat colDistM, const Mat bgWeight, const Mat fgWeight, Mat& saliencyOptimized, double neiSigma, double bgLambda )
94+
{
95+
96+
Mat smoothWeight = colDistM.clone();
97+
Mat smoothDeri = Mat(smoothWeight.size[0], smoothWeight.size[1], CV_64F, Scalar::all(0.0));
98+
Mat bgWeightDig = Mat(smoothWeight.size[0], smoothWeight.size[1], CV_64F, Scalar::all(0.0));
99+
Mat fgWeightDig = Mat(smoothWeight.size[0], smoothWeight.size[1], CV_64F, Scalar::all(0.0));
100+
Mat temp;
101+
102+
double mi = 0, ma = 0;
103+
minMaxLoc( fgWeight, &mi, &ma );
104+
Mat fg = fgWeight.clone();
105+
fg -= mi;
106+
fg /= ( ma - mi + 0.000001 );
107+
fg *= 255;
108+
fg.convertTo(fg, CV_8U);
109+
threshold(fg, fg, 0, 255, THRESH_TOZERO | THRESH_OTSU);
110+
fg.convertTo(fg, CV_64F);
111+
fg /= 255; // clean fore ground cue
112+
113+
minMaxLoc( smoothWeight, NULL, &ma );
114+
for ( int i = 0; i < smoothWeight.size[0]; i++ )
115+
{
116+
for ( int j = 0; j < smoothWeight.size[1]; j++ )
117+
{
118+
if ( adjcMatrix.at<uchar>(i, j) == 0 )
119+
{
120+
smoothWeight.at<double>(i, j) = ma * adjcMatrix.size[0];
121+
}
122+
}
123+
}
124+
125+
dist2WeightMatrix(smoothWeight, smoothWeight, neiSigma);
126+
adjcMatrix.convertTo(temp, CV_64F);
127+
smoothWeight += temp * 0.1;//add small coefficients for regularization term
128+
reduce(smoothWeight, temp, 0, REDUCE_SUM);
129+
for ( int i = 0; i < smoothDeri.size[0]; i++ )
130+
{
131+
smoothDeri.at<double>(i, i) = temp.at<double>(0, i);
132+
}
133+
for ( int i = 0; i < bgWeightDig.size[0]; i++ )
134+
{
135+
bgWeightDig.at<double>(i, i) = bgWeight.at<double>(i, 0) * bgLambda;
136+
}
137+
for ( int i = 0; i < fgWeightDig.size[0]; i++ )
138+
{
139+
fgWeightDig.at<double>(i, i) = fg.at<double>(i, 0);
140+
}
141+
//temp = (smoothDeri - smoothWeight + bgWeightDig + fgWeightDig);
142+
//saliencyOptimized = temp.inv() * fgWeight;
143+
solve((smoothDeri - smoothWeight + bgWeightDig + fgWeightDig), fg, saliencyOptimized, DECOMP_NORMAL);
68144
}
69145

70146
bool BackgroundContrast::computeSaliencyImpl( InputArray image, OutputArray saliencyMap )
@@ -75,7 +151,7 @@ bool BackgroundContrast::computeSaliencyImpl( InputArray image, OutputArray sali
75151
void BackgroundContrast::superpixelSplit( const Mat img, Mat& idxImg, Mat& adjcMatrix)
76152
{
77153
Ptr<SuperpixelSEEDS> seeds;
78-
seeds = createSuperpixelSEEDS( img.size().width, img.size().height, img.channels(), min(img.size().width * img.size().height / 600, 3000), 4, 2, 5, false);
154+
seeds = createSuperpixelSEEDS( img.size().width, img.size().height, img.channels(), min(img.size().width * img.size().height / 600, 600), 4, 2, 5, false);
79155
seeds->iterate( img, 4 );
80156
Mat mask;
81157
adjcMatrix = Mat::eye( seeds->getNumberOfSuperpixels(), seeds->getNumberOfSuperpixels(), CV_8U );
@@ -194,7 +270,7 @@ void BackgroundContrast::boundaryConnectivity(const Mat adjcMatrix, const Mat co
194270
}
195271
}
196272
}
197-
for ( int k = 0; k < adjcMatrix.size[0]; k++ )
273+
for ( int k = 0; k < adjcMatrix.size[0]; k++ ) // floyd algorithm, you can replace it with johnson algorithm but it's too long
198274
{
199275
for ( int i = 0; i < adjcMatrix.size[0]; i++ )
200276
{

0 commit comments

Comments
 (0)