NDNGestureVision::NDNGestureVision(int imageWidth, int imageHeight, int scanningStep, float minFlowThreshold, int numOfFlows)
: m_imageWidth(imageWidth), m_imageHeight(imageHeight), m_scanningStep(scanningStep), m_numOfFlows(numOfFlows)
{
- assert(imageWidth > 0 && imageHeight > 0 && scanningStep > 0);
+ assert(imageWidth > 0 && imageHeight > 0 && scanningStep > 0);
- m_scanningXMax = imageWidth / scanningStep;
- m_scanningYMax = imageHeight / scanningStep;
- m_mapSize = m_scanningXMax * m_scanningYMax;
+ m_scanningXMax = imageWidth / scanningStep;
+ m_scanningYMax = imageHeight / scanningStep;
+ m_mapSize = m_scanningXMax * m_scanningYMax;
m_map = cv::Mat(m_scanningYMax, m_scanningXMax, CV_8U);
m_minFlowThresholdP2 = minFlowThreshold * minFlowThreshold;
m_tempSortedFlowNums = new int[numOfFlows * 2];
NDNGestureVision::~NDNGestureVision()
{
if (m_tempSortedFlowNums)
- {
- delete [] m_tempSortedFlowNums;
- }
- if (m_tempSortedFlowExtents)
- {
- delete [] m_tempSortedFlowExtents;
- }
+ {
+ delete [] m_tempSortedFlowNums;
+ }
+ if (m_tempSortedFlowExtents)
+ {
+ delete [] m_tempSortedFlowExtents;
+ }
}
const NDNGestureVision::FlowRegion* NDNGestureVision::getFlow(int index) const
cv::cvtColor(newImage, newGrayScaleImage, CV_BGR2GRAY);
if( m_prevGray.data )
- {
+ {
/*-------------------
* Find flow regions
*/
cv::calcOpticalFlowFarneback(m_prevGray, newGrayScaleImage, flowMat, 0.5, 3, 15, 3, 5, 1.2, 0);
m_map = cv::Mat::zeros(m_map.size(),CV_8U);
- std::vector<FlowRegion> flowRegions;
- FlowRegion dummy;
- flowRegions.push_back(dummy);
+ std::vector<FlowRegion> flowRegions;
+ FlowRegion dummy;
+ flowRegions.push_back(dummy);
- int nextRegionNum = 1;
- for(int y = 0; y < m_scanningYMax; y++)
- {
- int x = 0;
+ int nextRegionNum = 1;
+ for(int y = 0; y < m_scanningYMax; y++)
+ {
+ int x = 0;
while(x < m_scanningXMax)
{
const cv::Point2f& fxy = flowMat.at<cv::Point2f>(y * m_scanningStep, x * m_scanningStep);
if (fxy.x * fxy.x + fxy.y * fxy.y <= m_minFlowThresholdP2)
- {
+ {
x++;
- }
- else
- {
- int extent = 1;
- float dxTotal = fxy.x;
- float dyTotal = fxy.y;
- std::set<int> attachingRegions;
+ }
+ else
+ {
+ int extent = 1;
+ float dxTotal = fxy.x;
+ float dyTotal = fxy.y;
+ std::set<int> attachingRegions;
int upperY = y - 1;
if (upperY >= 0)
- {
+ {
if (m_map.at<uchar>(upperY, x) > 0)
- {
+ {
attachingRegions.insert(m_map.at<uchar>(upperY,x));
- }
- }
- int ry = y * m_scanningStep;
- int sp = x;
- int xp = x + 1;
+ }
+ }
+ int ry = y * m_scanningStep;
+ int sp = x;
+ int xp = x + 1;
int rx = xp * m_scanningStep;
- while (xp < m_scanningXMax)
- {
+ while (xp < m_scanningXMax)
+ {
const cv::Point2f& rfxy = flowMat.at<cv::Point2f>(ry, rx);
if (rfxy.dot(fxy) < 0 || rfxy.x * rfxy.x + rfxy.y * rfxy.y < m_minFlowThresholdP2)
- break;
+ break;
- dxTotal += rfxy.x;
- dyTotal += rfxy.y;
- extent++;
+ dxTotal += rfxy.x;
+ dyTotal += rfxy.y;
+ extent++;
if (upperY >= 0 && m_map.at<uchar>(upperY, xp) > 0)
- {
+ {
attachingRegions.insert(m_map.at<uchar>(upperY, xp));
- }
- xp++;
+ }
+ xp++;
rx += m_scanningStep;
- }
- int ep = xp;
+ }
+ int ep = xp;
cv::Point2f direction;
direction.x = dxTotal / extent;
direction.x = direction.x / distance;
direction.y = direction.y / distance;
- std::set<int>::iterator it = attachingRegions.begin();
- int mapNum = 0;
- float maxR = 0;
- while(it != attachingRegions.end())
- {
- float r = flowRegions[*it].direction.dot(direction);
- if (r > 0 && maxR < r)
- {
- maxR = r;
- mapNum = *it;
- }
- ++it;
- }
-
- int regionNum = 0;
- if (maxR > 0)
- {
- regionNum = mapNum;
+ std::set<int>::iterator it = attachingRegions.begin();
+ int mapNum = 0;
+ float maxR = 0;
+ while(it != attachingRegions.end())
+ {
+ float r = flowRegions[*it].direction.dot(direction);
+ if (r > 0 && maxR < r)
+ {
+ maxR = r;
+ mapNum = *it;
+ }
+ ++it;
+ }
+
+ int regionNum = 0;
+ if (maxR > 0)
+ {
+ regionNum = mapNum;
float rate = ((float)extent) / ((float)(flowRegions[regionNum].extent + extent));
- direction.x = flowRegions[regionNum].direction.x * (1.0f - rate) + direction.x * rate;
- direction.y = flowRegions[regionNum].direction.y * (1.0f - rate) + direction.y * rate;
- float adj = 1.0f / sqrt(direction.x * direction.x + direction.y * direction.y);
- flowRegions[regionNum].direction.x = direction.x * adj;
- flowRegions[regionNum].direction.y = direction.y * adj;
- flowRegions[regionNum].distance = flowRegions[regionNum].distance * (1.0f -rate) + distance * rate;
- flowRegions[regionNum].extent = flowRegions[regionNum].extent + extent;
- if (sp * m_scanningStep < flowRegions[regionNum].xmin)
- {
- flowRegions[regionNum].xmin = sp * m_scanningStep;
- }
- if (flowRegions[regionNum].xmax < (ep - 1) * m_scanningStep)
- {
- flowRegions[regionNum].xmax = (ep - 1) * m_scanningStep;
- }
- flowRegions[regionNum].ymax = y * m_scanningStep;
- }
+ direction.x = flowRegions[regionNum].direction.x * (1.0f - rate) + direction.x * rate;
+ direction.y = flowRegions[regionNum].direction.y * (1.0f - rate) + direction.y * rate;
+ float adj = 1.0f / sqrt(direction.x * direction.x + direction.y * direction.y);
+ flowRegions[regionNum].direction.x = direction.x * adj;
+ flowRegions[regionNum].direction.y = direction.y * adj;
+ flowRegions[regionNum].distance = flowRegions[regionNum].distance * (1.0f -rate) + distance * rate;
+ flowRegions[regionNum].extent = flowRegions[regionNum].extent + extent;
+ if (sp * m_scanningStep < flowRegions[regionNum].xmin)
+ {
+ flowRegions[regionNum].xmin = sp * m_scanningStep;
+ }
+ if (flowRegions[regionNum].xmax < (ep - 1) * m_scanningStep)
+ {
+ flowRegions[regionNum].xmax = (ep - 1) * m_scanningStep;
+ }
+ flowRegions[regionNum].ymax = y * m_scanningStep;
+ }
else
- {
- FlowRegion flowRegion;
- flowRegion.extent = extent;
- flowRegion.direction = direction;
- flowRegion.distance = distance;
- flowRegion.xmin = sp * m_scanningStep;
- flowRegion.xmax = (ep - 1) * m_scanningStep;
- flowRegion.ymin = y * m_scanningStep;
- flowRegion.ymax = flowRegion.ymin;
-
- flowRegions.push_back(flowRegion);
- regionNum = nextRegionNum;
- nextRegionNum++;
-
- assert(nextRegionNum == flowRegions.size());
- }
+ {
+ FlowRegion flowRegion;
+ flowRegion.extent = extent;
+ flowRegion.direction = direction;
+ flowRegion.distance = distance;
+ flowRegion.xmin = sp * m_scanningStep;
+ flowRegion.xmax = (ep - 1) * m_scanningStep;
+ flowRegion.ymin = y * m_scanningStep;
+ flowRegion.ymax = flowRegion.ymin;
+
+ flowRegions.push_back(flowRegion);
+ regionNum = nextRegionNum;
+ nextRegionNum++;
+
+ assert(nextRegionNum == flowRegions.size());
+ }
for (int i = sp; i < ep; i++)
- {
+ {
m_map.at<uchar>(y, i) = regionNum;
- }
- x = ep;
- }
- }
- }
+ }
+ x = ep;
+ }
+ }
+ }
- for (int i = 0; i < m_numOfFlows * 2; i++)
- {
- m_tempSortedFlowNums[i] = 0;
- m_tempSortedFlowExtents[i] = 0;
- }
+ for (int i = 0; i < m_numOfFlows * 2; i++)
+ {
+ m_tempSortedFlowNums[i] = 0;
+ m_tempSortedFlowExtents[i] = 0;
+ }
- int sortedFlowSizeMax = nextRegionNum <= m_numOfFlows * 2 ? nextRegionNum - 1 : m_numOfFlows * 2;
+ int sortedFlowSizeMax = nextRegionNum <= m_numOfFlows * 2 ? nextRegionNum - 1 : m_numOfFlows * 2;
/*-------------------
* Sort flowRegions with its extents and put the region numbers into m_tempSortedFlowNums[], m_tempSortedFlowExtents[]
* The size of the list is stored in sortedFlowSize.
*/
- int cnt = 0;
- for (int i = 1 ; i < nextRegionNum; i++)
- {
+ int cnt = 0;
+ for (int i = 1 ; i < nextRegionNum; i++)
+ {
if (flowRegions[i].extent <= m_minExt)
- continue;
+ continue;
- for (int j = 0; j < sortedFlowSizeMax; j++)
- {
+ for (int j = 0; j < sortedFlowSizeMax; j++)
+ {
if (flowRegions[i].extent > m_tempSortedFlowExtents[j])
- {
+ {
for (int k = sortedFlowSizeMax - 2; k >= j; k--)
- {
- m_tempSortedFlowNums[k + 1] = m_tempSortedFlowNums[k];
- m_tempSortedFlowExtents[k + 1] = m_tempSortedFlowExtents[k];
- }
- m_tempSortedFlowNums[j] = i;
+ {
+ m_tempSortedFlowNums[k + 1] = m_tempSortedFlowNums[k];
+ m_tempSortedFlowExtents[k + 1] = m_tempSortedFlowExtents[k];
+ }
+ m_tempSortedFlowNums[j] = i;
m_tempSortedFlowExtents[j] = flowRegions[i].extent;
- cnt++;
- break;
- }
- }
- }
+ cnt++;
+ break;
+ }
+ }
+ }
int sortedFlowSize = sortedFlowSizeMax < cnt ? sortedFlowSizeMax : cnt;
/*-------------------
if (dmin < range * range)
{
cv::Point2f direction = flowRegions[m_tempSortedFlowNums[idx]].direction;
- if (abs(direction.x) < abs(direction.y))
- {
+
+ if (direction.y != 0)
expectedFlowDirectionY = direction.y < 0 ? -1 : 1;
- }
- else
- {
+
+ if (direction.x != 0)
expectedFlowDirectionX = direction.x < 0 ? -1 : 1;
- }
+
focusedRegionMoving = true;
}
}
int ey = range - step;
if (expectedFlowDirectionX > 0)
- sx /= 3;
+ sx = 0;
else if (expectedFlowDirectionX < 0)
- ex /= 3;
+ ex = 0;
if (expectedFlowDirectionY > 0)
- sy /= 3;
+ sy = 0;
else if (expectedFlowDirectionY < 0)
- ey /= 3;
+ ey = 0;
for (int y = sy; y <= ey; y += step)
{
stillPointCnt++;
int d = calcColorDiff(m_backgroundImage.at<cv::Vec3b>(iy,ix), newImage.at<cv::Vec3b>(iy,ix));
if (d > m_backgroundDiffThreshold)
- {
+ {
stillPointChangedPCnt++;
stillPointChangePSum += d;
}
* Draw output mat
*/
if (pGestureVisionDrawMat)
- {
+ {
int xs = pGestureVisionDrawMat->size().width / 4;
int ys = pGestureVisionDrawMat->size().height / 4;
}
}
- newGrayScaleImage.copyTo(m_prevGray);
+ newGrayScaleImage.copyTo(m_prevGray);
}
cv::Rect NDNGestureVision::findFingures(CvSeq *contour, std::vector<cv::Point>& fingures)