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.
244 lines
5.8 KiB
C++
244 lines
5.8 KiB
C++
#include "DynamicProgramSearch.h"
|
|
#include <list>
|
|
|
|
using std::list;
|
|
|
|
void dynamicProgramY(Mat& disMat, int n /*= 2*/)
|
|
{
|
|
for (int y = 1; y < disMat.rows; ++y)
|
|
{
|
|
for (int x = 0; x < disMat.cols; ++x)
|
|
{
|
|
// find max neighbor
|
|
int sy = y - 1;
|
|
float maxVal = -1;
|
|
int sj = x - n >= 0 ? x - n : 0;
|
|
int ej = x + n <= disMat.cols - 1 ? x + n : disMat.cols - 1;
|
|
for (int j = sj; j <= ej; j++)
|
|
{
|
|
float val = disMat.at<float>(sy, j);
|
|
if (maxVal < val)
|
|
{
|
|
maxVal = val;
|
|
}
|
|
}
|
|
|
|
disMat.at<float>(y, x) += maxVal;
|
|
}
|
|
}
|
|
}
|
|
|
|
void dynamicProgramX(Mat& disMat, int n /*= 2*/)
|
|
{
|
|
for (int x = 1; x < disMat.cols; ++x)
|
|
{
|
|
int sx = x - 1;
|
|
for (int y = 0; y < disMat.rows; ++y)
|
|
{
|
|
// find max neighbor
|
|
float maxVal = -1;
|
|
int si = max(y - n, 0);
|
|
int ei = min(y + n, disMat.rows - 1);
|
|
for (int i = si; i <= ei; i++)
|
|
{
|
|
float val = disMat.at<float>(i, sx);
|
|
if (maxVal < val)
|
|
{
|
|
maxVal = val;
|
|
}
|
|
}
|
|
|
|
disMat.at<float>(y, x) += maxVal;
|
|
}
|
|
}
|
|
}
|
|
|
|
void findMaxXPath(const Mat& disMat, vector<int>& vec, vector<float>& energyVec,
|
|
int n /*= 2*/)
|
|
{
|
|
int sy = 0;
|
|
int ey = disMat.rows - 1;
|
|
vec.resize(disMat.cols, -1);
|
|
energyVec.resize(disMat.cols, -1);
|
|
for (int x = disMat.cols - 1; x >= 0; --x)
|
|
{
|
|
float maxVal = -1;
|
|
int maxIdx = -1;
|
|
for (int y = sy; y <= ey; ++y)
|
|
{
|
|
float val = disMat.at<float>(y, x);
|
|
if (maxVal < val)
|
|
{
|
|
maxVal = val;
|
|
maxIdx = y;
|
|
}
|
|
}
|
|
vec[x] = maxIdx;
|
|
energyVec[x] = maxVal;
|
|
sy = maxIdx - n;
|
|
ey = maxIdx + n;
|
|
sy = (sy >= 0 ? sy : 0);
|
|
ey = (ey < disMat.rows ? ey : disMat.rows - 1);
|
|
}
|
|
}
|
|
|
|
void findMaxYPath(const Mat& disMat, vector<int>& vec, vector<float>& energyVec, int n /*= 2*/)
|
|
{
|
|
int sx = 0;
|
|
int ex = disMat.cols - 1;
|
|
vec.resize(disMat.rows, -1);
|
|
energyVec.resize(disMat.rows, -1);
|
|
for (int y = disMat.rows - 1; y >= 0; --y)
|
|
{
|
|
float maxVal = -1;
|
|
int maxIdx = -1;
|
|
for (int x = sx; x <= ex; ++x)
|
|
{
|
|
float val = disMat.at<float>(y, x);
|
|
if (maxVal < val)
|
|
{
|
|
maxVal = val;
|
|
maxIdx = x;
|
|
}
|
|
}
|
|
vec[y] = maxIdx;
|
|
energyVec[y] = maxVal;
|
|
sx = maxIdx - n;
|
|
ex = maxIdx + n;
|
|
sx = (sx >= 0 ? sx : 0);
|
|
ex = (ex < disMat.cols ? ex : disMat.cols - 1);
|
|
}
|
|
}
|
|
|
|
void recoverPathEnergy(vector<float>& vec)
|
|
{
|
|
assert(!vec.empty());
|
|
|
|
auto i = vec.rbegin();
|
|
auto j = i;
|
|
++j;
|
|
while (j != vec.rend())
|
|
{
|
|
*i = *i - *j;
|
|
++i;
|
|
++j;
|
|
}
|
|
}
|
|
|
|
void dynamicProgramYWithSmooth(Mat& disMat,
|
|
int n /*= 2*/, float sw /*= 1.0*/,
|
|
const Mat& smoothMat /*= Mat()*/)
|
|
{
|
|
for (int y = 1; y < disMat.rows; ++y)
|
|
{
|
|
for (int x = 0; x < disMat.cols; ++x)
|
|
{
|
|
// find max neighbor
|
|
int sy = y - 1;
|
|
float maxVal = -1;
|
|
int sj = x - n >= 0 ? x - n : 0;
|
|
int ej = x + n <= disMat.cols - 1 ? x + n : disMat.cols - 1;
|
|
float baseSVal = 0;
|
|
if (!smoothMat.empty())
|
|
{
|
|
baseSVal = smoothMat.at<float>(y, x);
|
|
}
|
|
for (int j = sj; j <= ej; j++)
|
|
{
|
|
float disVal = disMat.at<float>(sy, j);
|
|
float sVal = 0;
|
|
if (!smoothMat.empty())
|
|
{
|
|
sVal = smoothMat.at<float>(sy, j);
|
|
}
|
|
float energyVal = disVal + (255 - abs(sVal - baseSVal))*sw;
|
|
if (maxVal < energyVal)
|
|
{
|
|
maxVal = energyVal;
|
|
}
|
|
}
|
|
|
|
disMat.at<float>(y, x) += maxVal;
|
|
}
|
|
}
|
|
}
|
|
|
|
void dynamicProgramYWithSmooth(Mat& disMat0, Mat& disMat1,
|
|
const Mat& smoothMat0,
|
|
const Mat& smoothMat1,
|
|
int targetWidth,
|
|
int n /* = 2 */,
|
|
float sw /* = 1.0 */)
|
|
{
|
|
assert(targetWidth <= disMat0.cols + disMat1.cols);
|
|
|
|
for (int y = 1; y < disMat0.rows; ++y)
|
|
{
|
|
int sx = 0;
|
|
int ex = disMat0.cols;
|
|
if (targetWidth < disMat0.cols)
|
|
{
|
|
sx = disMat0.cols - targetWidth;
|
|
}
|
|
if (targetWidth > disMat1.cols)
|
|
{
|
|
ex = disMat0.cols - (targetWidth - disMat1.cols);
|
|
}
|
|
|
|
for (int x = sx; x < ex; ++x)
|
|
{
|
|
// find max neighbor
|
|
int sy = y - 1;
|
|
float maxVal = -1;
|
|
int sj0 = x - n >= 0 ? x - n : 0;
|
|
int ej0 = x + n <= disMat0.cols - 1 ? x + n : disMat0.cols - 1;
|
|
int sj1 = sj0 + targetWidth - disMat0.cols;
|
|
int ej1 = ej0 + targetWidth - disMat0.cols;
|
|
if (sj1 < 0)
|
|
{
|
|
sj0 += -sj1;
|
|
}
|
|
if (ej1 > disMat1.cols - 1)
|
|
{
|
|
ej0 -= ej1 - disMat1.cols + 1;
|
|
}
|
|
float baseSVal0 = 0;
|
|
if (!smoothMat0.empty())
|
|
{
|
|
baseSVal0 = smoothMat0.at<float>(y, x);
|
|
}
|
|
float baseSVal1 = 0;
|
|
if (!smoothMat1.empty())
|
|
{
|
|
baseSVal1 = smoothMat1.at<float>(y, x + targetWidth - smoothMat0.cols);
|
|
}
|
|
for (int j = sj0; j <= ej0; j++)
|
|
{
|
|
float disVal0 = disMat0.at<float>(sy, j);
|
|
int j1 = j + targetWidth - disMat0.cols;
|
|
float disVal1 = disMat1.at<float>(sy, j1);
|
|
float sVal0 = 0;
|
|
if (!smoothMat0.empty())
|
|
{
|
|
sVal0 = smoothMat0.at<float>(sy, j);
|
|
}
|
|
float sVal1 = 0;
|
|
if (!smoothMat1.empty())
|
|
{
|
|
sVal1 = smoothMat1.at<float>(sy, j1);
|
|
}
|
|
float energyVal = disVal0 + disVal1 +
|
|
(255 - abs(sVal0 - baseSVal0))*sw +
|
|
(255 - abs(sVal1 - baseSVal1))*sw;
|
|
if (maxVal < energyVal)
|
|
{
|
|
maxVal = energyVal;
|
|
}
|
|
}
|
|
|
|
disMat0.at<float>(y, x) += maxVal;
|
|
}
|
|
}
|
|
}
|
|
|