"atomic bomb" commit. Reorganized OpenCV directory structure

This commit is contained in:
Vadim Pisarevsky
2010-05-11 17:44:00 +00:00
commit 127d6649a1
1761 changed files with 1766340 additions and 0 deletions

View File

@@ -0,0 +1,588 @@
/*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) 2002, 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:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions 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"
#if _MSC_VER >= 1200
#pragma warning(disable:4786) // Disable MSVC warnings in the standard library.
#pragma warning(disable:4100)
#pragma warning(disable:4512)
#endif
#include <stdio.h>
#include <map>
#include <algorithm>
#if _MSC_VER >= 1200
#pragma warning(default:4100)
#pragma warning(default:4512)
#endif
#define ARRAY_SIZEOF(a) (sizeof(a)/sizeof((a)[0]))
static void FillObjectPoints(CvPoint3D32f *obj_points, CvSize etalon_size, float square_size);
static void DrawEtalon(IplImage *img, CvPoint2D32f *corners,
int corner_count, CvSize etalon_size, int draw_ordered);
static void MultMatrix(float rm[4][4], const float m1[4][4], const float m2[4][4]);
static void MultVectorMatrix(float rv[4], const float v[4], const float m[4][4]);
static CvPoint3D32f ImageCStoWorldCS(const Cv3dTrackerCameraInfo &camera_info, CvPoint2D32f p);
static bool intersection(CvPoint3D32f o1, CvPoint3D32f p1,
CvPoint3D32f o2, CvPoint3D32f p2,
CvPoint3D32f &r1, CvPoint3D32f &r2);
/////////////////////////////////
// cv3dTrackerCalibrateCameras //
/////////////////////////////////
CV_IMPL CvBool cv3dTrackerCalibrateCameras(int num_cameras,
const Cv3dTrackerCameraIntrinsics camera_intrinsics[], // size is num_cameras
CvSize etalon_size,
float square_size,
IplImage *samples[], // size is num_cameras
Cv3dTrackerCameraInfo camera_info[]) // size is num_cameras
{
CV_FUNCNAME("cv3dTrackerCalibrateCameras");
const int num_points = etalon_size.width * etalon_size.height;
int cameras_done = 0; // the number of cameras whose positions have been determined
CvPoint3D32f *object_points = NULL; // real-world coordinates of checkerboard points
CvPoint2D32f *points = NULL; // 2d coordinates of checkerboard points as seen by a camera
IplImage *gray_img = NULL; // temporary image for color conversion
IplImage *tmp_img = NULL; // temporary image used by FindChessboardCornerGuesses
int c, i, j;
if (etalon_size.width < 3 || etalon_size.height < 3)
CV_ERROR(CV_StsBadArg, "Chess board size is invalid");
for (c = 0; c < num_cameras; c++)
{
// CV_CHECK_IMAGE is not available in the cvaux library
// so perform the checks inline.
//CV_CALL(CV_CHECK_IMAGE(samples[c]));
if( samples[c] == NULL )
CV_ERROR( CV_HeaderIsNull, "Null image" );
if( samples[c]->dataOrder != IPL_DATA_ORDER_PIXEL && samples[c]->nChannels > 1 )
CV_ERROR( CV_BadOrder, "Unsupported image format" );
if( samples[c]->maskROI != 0 || samples[c]->tileInfo != 0 )
CV_ERROR( CV_StsBadArg, "Unsupported image format" );
if( samples[c]->imageData == 0 )
CV_ERROR( CV_BadDataPtr, "Null image data" );
if( samples[c]->roi &&
((samples[c]->roi->xOffset | samples[c]->roi->yOffset
| samples[c]->roi->width | samples[c]->roi->height) < 0 ||
samples[c]->roi->xOffset + samples[c]->roi->width > samples[c]->width ||
samples[c]->roi->yOffset + samples[c]->roi->height > samples[c]->height ||
(unsigned) (samples[c]->roi->coi) > (unsigned) (samples[c]->nChannels)))
CV_ERROR( CV_BadROISize, "Invalid ROI" );
// End of CV_CHECK_IMAGE inline expansion
if (samples[c]->depth != IPL_DEPTH_8U)
CV_ERROR(CV_BadDepth, "Channel depth of source image must be 8");
if (samples[c]->nChannels != 3 && samples[c]->nChannels != 1)
CV_ERROR(CV_BadNumChannels, "Source image must have 1 or 3 channels");
}
CV_CALL(object_points = (CvPoint3D32f *)cvAlloc(num_points * sizeof(CvPoint3D32f)));
CV_CALL(points = (CvPoint2D32f *)cvAlloc(num_points * sizeof(CvPoint2D32f)));
// fill in the real-world coordinates of the checkerboard points
FillObjectPoints(object_points, etalon_size, square_size);
for (c = 0; c < num_cameras; c++)
{
CvSize image_size = cvSize(samples[c]->width, samples[c]->height);
IplImage *img;
// The input samples are not required to all have the same size or color
// format. If they have different sizes, the temporary images are
// reallocated as necessary.
if (samples[c]->nChannels == 3)
{
// convert to gray
if (gray_img == NULL || gray_img->width != samples[c]->width ||
gray_img->height != samples[c]->height )
{
if (gray_img != NULL)
cvReleaseImage(&gray_img);
CV_CALL(gray_img = cvCreateImage(image_size, IPL_DEPTH_8U, 1));
}
CV_CALL(cvCvtColor(samples[c], gray_img, CV_BGR2GRAY));
img = gray_img;
}
else
{
// no color conversion required
img = samples[c];
}
if (tmp_img == NULL || tmp_img->width != samples[c]->width ||
tmp_img->height != samples[c]->height )
{
if (tmp_img != NULL)
cvReleaseImage(&tmp_img);
CV_CALL(tmp_img = cvCreateImage(image_size, IPL_DEPTH_8U, 1));
}
int count = num_points;
bool found = cvFindChessBoardCornerGuesses(img, tmp_img, 0,
etalon_size, points, &count) != 0;
if (count == 0)
continue;
// If found is true, it means all the points were found (count = num_points).
// If found is false but count is non-zero, it means that not all points were found.
cvFindCornerSubPix(img, points, count, cvSize(5,5), cvSize(-1,-1),
cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS, 10, 0.01f));
// If the image origin is BL (bottom-left), fix the y coordinates
// so they are relative to the true top of the image.
if (samples[c]->origin == IPL_ORIGIN_BL)
{
for (i = 0; i < count; i++)
points[i].y = samples[c]->height - 1 - points[i].y;
}
if (found)
{
// Make sure x coordinates are increasing and y coordinates are decreasing.
// (The y coordinate of point (0,0) should be the greatest, because the point
// on the checkerboard that is the origin is nearest the bottom of the image.)
// This is done after adjusting the y coordinates according to the image origin.
if (points[0].x > points[1].x)
{
// reverse points in each row
for (j = 0; j < etalon_size.height; j++)
{
CvPoint2D32f *row = &points[j*etalon_size.width];
for (i = 0; i < etalon_size.width/2; i++)
std::swap(row[i], row[etalon_size.width-i-1]);
}
}
if (points[0].y < points[etalon_size.width].y)
{
// reverse points in each column
for (i = 0; i < etalon_size.width; i++)
{
for (j = 0; j < etalon_size.height/2; j++)
std::swap(points[i+j*etalon_size.width],
points[i+(etalon_size.height-j-1)*etalon_size.width]);
}
}
}
DrawEtalon(samples[c], points, count, etalon_size, found);
if (!found)
continue;
float rotVect[3];
float rotMatr[9];
float transVect[3];
cvFindExtrinsicCameraParams(count,
image_size,
points,
object_points,
const_cast<float *>(camera_intrinsics[c].focal_length),
camera_intrinsics[c].principal_point,
const_cast<float *>(camera_intrinsics[c].distortion),
rotVect,
transVect);
// Check result against an arbitrary limit to eliminate impossible values.
// (If the chess board were truly that far away, the camera wouldn't be able to
// see the squares.)
if (transVect[0] > 1000*square_size
|| transVect[1] > 1000*square_size
|| transVect[2] > 1000*square_size)
{
// ignore impossible results
continue;
}
CvMat rotMatrDescr = cvMat(3, 3, CV_32FC1, rotMatr);
CvMat rotVectDescr = cvMat(3, 1, CV_32FC1, rotVect);
/* Calc rotation matrix by Rodrigues Transform */
cvRodrigues2( &rotVectDescr, &rotMatrDescr );
//combine the two transformations into one matrix
//order is important! rotations are not commutative
float tmat[4][4] = { { 1.f, 0.f, 0.f, 0.f },
{ 0.f, 1.f, 0.f, 0.f },
{ 0.f, 0.f, 1.f, 0.f },
{ transVect[0], transVect[1], transVect[2], 1.f } };
float rmat[4][4] = { { rotMatr[0], rotMatr[1], rotMatr[2], 0.f },
{ rotMatr[3], rotMatr[4], rotMatr[5], 0.f },
{ rotMatr[6], rotMatr[7], rotMatr[8], 0.f },
{ 0.f, 0.f, 0.f, 1.f } };
MultMatrix(camera_info[c].mat, tmat, rmat);
// change the transformation of the cameras to put them in the world coordinate
// system we want to work with.
// Start with an identity matrix; then fill in the values to accomplish
// the desired transformation.
float smat[4][4] = { { 1.f, 0.f, 0.f, 0.f },
{ 0.f, 1.f, 0.f, 0.f },
{ 0.f, 0.f, 1.f, 0.f },
{ 0.f, 0.f, 0.f, 1.f } };
// First, reflect through the origin by inverting all three axes.
smat[0][0] = -1.f;
smat[1][1] = -1.f;
smat[2][2] = -1.f;
MultMatrix(tmat, camera_info[c].mat, smat);
// Scale x and y coordinates by the focal length (allowing for non-square pixels
// and/or non-symmetrical lenses).
smat[0][0] = 1.0f / camera_intrinsics[c].focal_length[0];
smat[1][1] = 1.0f / camera_intrinsics[c].focal_length[1];
smat[2][2] = 1.0f;
MultMatrix(camera_info[c].mat, smat, tmat);
camera_info[c].principal_point = camera_intrinsics[c].principal_point;
camera_info[c].valid = true;
cameras_done++;
}
exit:
cvReleaseImage(&gray_img);
cvReleaseImage(&tmp_img);
cvFree(&object_points);
cvFree(&points);
return cameras_done == num_cameras;
}
// fill in the real-world coordinates of the checkerboard points
static void FillObjectPoints(CvPoint3D32f *obj_points, CvSize etalon_size, float square_size)
{
int x, y, i;
for (y = 0, i = 0; y < etalon_size.height; y++)
{
for (x = 0; x < etalon_size.width; x++, i++)
{
obj_points[i].x = square_size * x;
obj_points[i].y = square_size * y;
obj_points[i].z = 0;
}
}
}
// Mark the points found on the input image
// The marks are drawn multi-colored if all the points were found.
static void DrawEtalon(IplImage *img, CvPoint2D32f *corners,
int corner_count, CvSize etalon_size, int draw_ordered)
{
const int r = 4;
int i;
int x, y;
CvPoint prev_pt = { 0, 0 };
static const CvScalar rgb_colors[] = {
{{0,0,255}},
{{0,128,255}},
{{0,200,200}},
{{0,255,0}},
{{200,200,0}},
{{255,0,0}},
{{255,0,255}} };
static const CvScalar gray_colors[] = {
{{80}}, {{120}}, {{160}}, {{200}}, {{100}}, {{140}}, {{180}}
};
const CvScalar* colors = img->nChannels == 3 ? rgb_colors : gray_colors;
CvScalar color = colors[0];
for (y = 0, i = 0; y < etalon_size.height; y++)
{
if (draw_ordered)
color = colors[y % ARRAY_SIZEOF(rgb_colors)];
for (x = 0; x < etalon_size.width && i < corner_count; x++, i++)
{
CvPoint pt;
pt.x = cvRound(corners[i].x);
pt.y = cvRound(corners[i].y);
if (img->origin == IPL_ORIGIN_BL)
pt.y = img->height - 1 - pt.y;
if (draw_ordered)
{
if (i != 0)
cvLine(img, prev_pt, pt, color, 1, CV_AA);
prev_pt = pt;
}
cvLine( img, cvPoint(pt.x - r, pt.y - r),
cvPoint(pt.x + r, pt.y + r), color, 1, CV_AA );
cvLine( img, cvPoint(pt.x - r, pt.y + r),
cvPoint(pt.x + r, pt.y - r), color, 1, CV_AA );
cvCircle( img, pt, r+1, color, 1, CV_AA );
}
}
}
// Find the midpoint of the line segment between two points.
static CvPoint3D32f midpoint(const CvPoint3D32f &p1, const CvPoint3D32f &p2)
{
return cvPoint3D32f((p1.x+p2.x)/2, (p1.y+p2.y)/2, (p1.z+p2.z)/2);
}
static void operator +=(CvPoint3D32f &p1, const CvPoint3D32f &p2)
{
p1.x += p2.x;
p1.y += p2.y;
p1.z += p2.z;
}
static CvPoint3D32f operator /(const CvPoint3D32f &p, int d)
{
return cvPoint3D32f(p.x/d, p.y/d, p.z/d);
}
static const Cv3dTracker2dTrackedObject *find(const Cv3dTracker2dTrackedObject v[], int num_objects, int id)
{
for (int i = 0; i < num_objects; i++)
{
if (v[i].id == id)
return &v[i];
}
return NULL;
}
#define CAMERA_POS(c) (cvPoint3D32f((c).mat[3][0], (c).mat[3][1], (c).mat[3][2]))
//////////////////////////////
// cv3dTrackerLocateObjects //
//////////////////////////////
CV_IMPL int cv3dTrackerLocateObjects(int num_cameras, int num_objects,
const Cv3dTrackerCameraInfo camera_info[], // size is num_cameras
const Cv3dTracker2dTrackedObject tracking_info[], // size is num_objects*num_cameras
Cv3dTrackerTrackedObject tracked_objects[]) // size is num_objects
{
/*CV_FUNCNAME("cv3dTrackerLocateObjects");*/
int found_objects = 0;
// count how many cameras could see each object
std::map<int, int> count;
for (int c = 0; c < num_cameras; c++)
{
if (!camera_info[c].valid)
continue;
for (int i = 0; i < num_objects; i++)
{
const Cv3dTracker2dTrackedObject *o = &tracking_info[c*num_objects+i];
if (o->id != -1)
count[o->id]++;
}
}
// process each object that was seen by at least two cameras
for (std::map<int, int>::iterator i = count.begin(); i != count.end(); i++)
{
if (i->second < 2)
continue; // ignore object seen by only one camera
int id = i->first;
// find an approximation of the objects location for each pair of cameras that
// could see this object, and average them
CvPoint3D32f total = cvPoint3D32f(0, 0, 0);
int weight = 0;
for (int c1 = 0; c1 < num_cameras-1; c1++)
{
if (!camera_info[c1].valid)
continue;
const Cv3dTracker2dTrackedObject *o1 = find(&tracking_info[c1*num_objects],
num_objects, id);
if (o1 == NULL)
continue; // this camera didn't see this object
CvPoint3D32f p1a = CAMERA_POS(camera_info[c1]);
CvPoint3D32f p1b = ImageCStoWorldCS(camera_info[c1], o1->p);
for (int c2 = c1 + 1; c2 < num_cameras; c2++)
{
if (!camera_info[c2].valid)
continue;
const Cv3dTracker2dTrackedObject *o2 = find(&tracking_info[c2*num_objects],
num_objects, id);
if (o2 == NULL)
continue; // this camera didn't see this object
CvPoint3D32f p2a = CAMERA_POS(camera_info[c2]);
CvPoint3D32f p2b = ImageCStoWorldCS(camera_info[c2], o2->p);
// these variables are initialized simply to avoid erroneous error messages
// from the compiler
CvPoint3D32f r1 = cvPoint3D32f(0, 0, 0);
CvPoint3D32f r2 = cvPoint3D32f(0, 0, 0);
// find the intersection of the two lines (or the points of closest
// approach, if they don't intersect)
if (!intersection(p1a, p1b, p2a, p2b, r1, r2))
continue;
total += midpoint(r1, r2);
weight++;
}
}
CvPoint3D32f center = total/weight;
tracked_objects[found_objects++] = cv3dTrackerTrackedObject(id, center);
}
return found_objects;
}
#define EPS 1e-9
// Compute the determinant of the 3x3 matrix represented by 3 row vectors.
static inline double det(CvPoint3D32f v1, CvPoint3D32f v2, CvPoint3D32f v3)
{
return v1.x*v2.y*v3.z + v1.z*v2.x*v3.y + v1.y*v2.z*v3.x
- v1.z*v2.y*v3.x - v1.x*v2.z*v3.y - v1.y*v2.x*v3.z;
}
static CvPoint3D32f operator +(CvPoint3D32f a, CvPoint3D32f b)
{
return cvPoint3D32f(a.x + b.x, a.y + b.y, a.z + b.z);
}
static CvPoint3D32f operator -(CvPoint3D32f a, CvPoint3D32f b)
{
return cvPoint3D32f(a.x - b.x, a.y - b.y, a.z - b.z);
}
static CvPoint3D32f operator *(CvPoint3D32f v, double f)
{
return cvPoint3D32f(f*v.x, f*v.y, f*v.z);
}
// Find the intersection of two lines, or if they don't intersect,
// the points of closest approach.
// The lines are defined by (o1,p1) and (o2, p2).
// If they intersect, r1 and r2 will be the same.
// Returns false on error.
static bool intersection(CvPoint3D32f o1, CvPoint3D32f p1,
CvPoint3D32f o2, CvPoint3D32f p2,
CvPoint3D32f &r1, CvPoint3D32f &r2)
{
CvPoint3D32f x = o2 - o1;
CvPoint3D32f d1 = p1 - o1;
CvPoint3D32f d2 = p2 - o2;
CvPoint3D32f cross = cvPoint3D32f(d1.y*d2.z - d1.z*d2.y,
d1.z*d2.x - d1.x*d2.z,
d1.x*d2.y - d1.y*d2.x);
double den = cross.x*cross.x + cross.y*cross.y + cross.z*cross.z;
if (den < EPS)
return false;
double t1 = det(x, d2, cross) / den;
double t2 = det(x, d1, cross) / den;
r1 = o1 + d1 * t1;
r2 = o2 + d2 * t2;
return true;
}
// Convert from image to camera space by transforming point p in
// the image plane by the camera matrix.
static CvPoint3D32f ImageCStoWorldCS(const Cv3dTrackerCameraInfo &camera_info, CvPoint2D32f p)
{
float tp[4];
tp[0] = (float)p.x - camera_info.principal_point.x;
tp[1] = (float)p.y - camera_info.principal_point.y;
tp[2] = 1.f;
tp[3] = 1.f;
float tr[4];
//multiply tp by mat to get tr
MultVectorMatrix(tr, tp, camera_info.mat);
return cvPoint3D32f(tr[0]/tr[3], tr[1]/tr[3], tr[2]/tr[3]);
}
// Multiply affine transformation m1 by the affine transformation m2 and
// return the result in rm.
static void MultMatrix(float rm[4][4], const float m1[4][4], const float m2[4][4])
{
for (int i=0; i<=3; i++)
for (int j=0; j<=3; j++)
{
rm[i][j]= 0.0;
for (int k=0; k <= 3; k++)
rm[i][j] += m1[i][k]*m2[k][j];
}
}
// Multiply the vector v by the affine transformation matrix m and return the
// result in rv.
void MultVectorMatrix(float rv[4], const float v[4], const float m[4][4])
{
for (int i=0; i<=3; i++)
{
rv[i] = 0.f;
for (int j=0;j<=3;j++)
rv[i] += v[j] * m[j][i];
}
}

View File

@@ -0,0 +1,412 @@
/*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*/
///////////////////////////////////////////////
//// Created by Khudyakov V.A. bober@gorodok.net
// FaceDetection.h: interface for the FaceDetection class.
//
//////////////////////////////////////////////////////////////////////
#ifndef _CVFACEDETECTION_H_
#define _CVFACEDETECTION_H_
#define MAX_LAYERS 64
class FaceFeature
{
public:
FaceFeature(double dWeight,void * lpContour,bool bIsFeature);
FaceFeature();
virtual ~FaceFeature();
inline bool isFaceFeature();
inline void * GetContour();
inline double GetWeight();
inline void SetContour(void * lpContour);
inline void SetWeight(double dWeight);
inline void SetFeature(bool bIsFeature);
private:
double m_dWeight;
void * m_lpContour;
bool m_bIsFaceFeature;
};//class FaceFeature
inline void FaceFeature::SetFeature(bool bIsFeature)
{
m_bIsFaceFeature = bIsFeature;
}
inline bool FaceFeature::isFaceFeature()
{
return m_bIsFaceFeature;
}//inline bool FaceFeature::isFaceFeature()
inline void * FaceFeature::GetContour()
{
return m_lpContour;
}//inline void * FaceFeature::GetContour()
inline double FaceFeature::GetWeight()
{
return m_dWeight;
}//inline long FaceFeature::GetWeight()
inline void FaceFeature::SetContour(void * lpContour)
{
m_lpContour = lpContour;
}//inline void FaceFeature::SetContour(void * lpContour)
inline void FaceFeature::SetWeight(double dWeight)
{
m_dWeight = dWeight;
}//inline void FaceFeature::SetWeight(double * dWeight)
class FaceTemplate
{
public:
FaceTemplate(long lFeatureCount) {m_lFeaturesCount = lFeatureCount; m_lpFeaturesList = new FaceFeature[lFeatureCount];};
virtual ~FaceTemplate();
inline long GetCount();
inline FaceFeature * GetFeatures();
protected:
FaceFeature * m_lpFeaturesList;
private:
long m_lFeaturesCount;
};//class FaceTemplate
inline long FaceTemplate::GetCount()
{
return m_lFeaturesCount;
}//inline long FaceTemplate::GetCount()
inline FaceFeature * FaceTemplate::GetFeatures()
{
return m_lpFeaturesList;
}//inline FaceFeature * FaceTemplate::GetFeatures()
////////////
//class RFaceTemplate
///////////
class MouthFaceTemplate:public FaceTemplate
{
public:
inline MouthFaceTemplate(long lNumber,CvRect rect,double dEyeWidth,double dEyeHeight,double dDistanceBetweenEye,double dDistanceEyeAboveMouth);
~MouthFaceTemplate();
};//class MouthFaceTemplate:public FaceTemplate
inline MouthFaceTemplate::MouthFaceTemplate(long lNumber,CvRect rect,double dEyeWidth,double dEyeHeight,
double dDistanceBetweenEye,double dDistanceEyeAboveMouth):FaceTemplate(lNumber)
{
CvRect MouthRect = rect;
CvRect LeftEyeRect = cvRect(cvRound(rect.x - (dEyeWidth + dDistanceBetweenEye/(double)2 - (double)rect.width/(double)2)),
cvRound(rect.y - dDistanceEyeAboveMouth - dEyeHeight),
cvRound(dEyeWidth),
cvRound(dEyeHeight) );
CvRect RightEyeRect = cvRect(cvRound(rect.x + (double)rect.width/(double)2 + dDistanceBetweenEye/(double)2),
cvRound(rect.y - dDistanceEyeAboveMouth - dEyeHeight),
cvRound(dEyeWidth),
cvRound(dEyeHeight) );
// CvRect NoseRect = cvRect(cvRound(rect.x + (double)rect.width/(double)4),
// cvRound(rect.y - (double)rect.width/(double)2 - (double)rect.height/(double)4),
// cvRound((double)rect.width/(double)2),
// cvRound((double)rect.width/(double)2) );
/*
CvRect CheenRect = cvRect(rect.x,rect.y + 3*rect.height/2,rect.width,rect.height);
*/
CvRect * lpMouthRect = new CvRect();
*lpMouthRect = MouthRect;
m_lpFeaturesList[0].SetContour(lpMouthRect);
m_lpFeaturesList[0].SetWeight(1);
m_lpFeaturesList[0].SetFeature(false);
CvRect * lpLeftEyeRect = new CvRect();
*lpLeftEyeRect = LeftEyeRect;
m_lpFeaturesList[1].SetContour(lpLeftEyeRect);
m_lpFeaturesList[1].SetWeight(1);
m_lpFeaturesList[1].SetFeature(true);
CvRect * lpRightEyeRect = new CvRect();
*lpRightEyeRect = RightEyeRect;
m_lpFeaturesList[2].SetContour(lpRightEyeRect);
m_lpFeaturesList[2].SetWeight(1);
m_lpFeaturesList[2].SetFeature(true);
// CvRect * lpNoseRect = new CvRect();
// *lpNoseRect = NoseRect;
// m_lpFeaturesList[3].SetContour(lpNoseRect);
// m_lpFeaturesList[3].SetWeight(0);
// m_lpFeaturesList[3].SetFeature(true);
/* CvRect * lpCheenRect = new CvRect();
*lpCheenRect = CheenRect;
m_lpFeaturesList[4].SetContour(lpCheenRect);
m_lpFeaturesList[4].SetWeight(1);
m_lpFeaturesList[4].SetFeature(false);
*/
}//constructor MouthFaceTemplate(long lNumFeatures,CvRect rect,double dEyeWidth,double dEyeHeight,double dDistanceBetweenEye,double dDistanceEyeAboveMouth);
typedef struct CvContourRect
{
int iNumber;
int iType;
int iFlags;
CvSeq *seqContour;
int iContourLength;
CvRect r;
CvPoint pCenter;
int iColor;
} CvContourRect;
class Face
{
public:
Face(FaceTemplate * lpFaceTemplate);
virtual ~Face();
inline bool isFeature(void * lpElem);
virtual void Show(IplImage * /*Image*/){};
virtual void ShowIdeal(IplImage* /*Image*/){};
virtual void CreateFace(void * lpData) = 0;
virtual bool CheckElem(void * lpCandidat,void * lpIdeal) = 0;
virtual double GetWeight() = 0;
protected:
FaceFeature * m_lpIdealFace;//ideal face definition
long m_lFaceFeaturesNumber; //total number of diferent face features
long * m_lplFaceFeaturesCount;//number of each features fouded for this face
FaceFeature ** m_lppFoundedFaceFeatures;//founded features of curen face
double m_dWeight;
};
inline bool Face::isFeature(void * lpElem)
{
for (int i = 0;i < m_lFaceFeaturesNumber;i ++)
{
void * lpIdeal = m_lpIdealFace[i].GetContour();
if ( CheckElem( lpElem,lpIdeal) )
{
if (m_lplFaceFeaturesCount[i] < 3*MAX_LAYERS)
{
double dWeight = m_lpIdealFace[i].GetWeight();
bool bIsFeature = m_lpIdealFace[i].isFaceFeature();
if (bIsFeature)
{
m_lppFoundedFaceFeatures[i][m_lplFaceFeaturesCount[i]].SetWeight(dWeight);
m_lppFoundedFaceFeatures[i][m_lplFaceFeaturesCount[i]].SetContour(lpElem);
m_lppFoundedFaceFeatures[i][m_lplFaceFeaturesCount[i]].SetFeature(bIsFeature);
m_lplFaceFeaturesCount[i] ++;
}
m_dWeight += dWeight;
if (bIsFeature)
return true;
}
}
}
return false;
}//inline bool RFace::isFeature(void * lpElem);
struct FaceData
{
CvRect LeftEyeRect;
CvRect RightEyeRect;
CvRect MouthRect;
double Error;
};//struct FaceData
class RFace:public Face
{
public:
RFace(FaceTemplate * lpFaceTemplate);
virtual ~RFace();
virtual bool CheckElem(void * lpCandidat,void * lpIdeal);
virtual void CreateFace(void * lpData);
virtual void Show(IplImage* Image);
virtual void ShowIdeal(IplImage* Image);
virtual double GetWeight();
private:
bool isPointInRect(CvPoint p,CvRect rect);
bool m_bIsGenerated;
void ResizeRect(CvRect Rect,CvRect * lpRect,long lDir,long lD);
void CalculateError(FaceData * lpFaceData);
};
class ListElem
{
public:
ListElem();
ListElem(Face * pFace,ListElem * pHead);
virtual ~ListElem();
ListElem * m_pNext;
ListElem * m_pPrev;
Face * m_pFace;
};//class ListElem
class List
{
public:
List();
int AddElem(Face * pFace);
virtual ~List();
Face* GetData();
long m_FacesCount;
private:
ListElem * m_pHead;
ListElem * m_pCurElem;
};//class List
class FaceDetection
{
public:
void FindFace(IplImage* img);
void CreateResults(CvSeq * lpSeq);
FaceDetection();
virtual ~FaceDetection();
void SetBoosting(bool bBoosting) {m_bBoosting = bBoosting;}
bool isPostBoosting() {return m_bBoosting;}
protected:
IplImage* m_imgGray;
IplImage* m_imgThresh;
int m_iNumLayers;
CvMemStorage* m_mstgContours;
CvSeq* m_seqContours[MAX_LAYERS];
CvMemStorage* m_mstgRects;
CvSeq* m_seqRects;
bool m_bBoosting;
List * m_pFaceList;
protected:
void ResetImage();
void FindContours(IplImage* imgGray);
void AddContours2Rect(CvSeq* seq, int color, int iLayer);
void ThresholdingParam(IplImage* imgGray, int iNumLayers, int& iMinLevel, int& iMaxLevel, int& iStep);
void FindCandidats();
void PostBoostingFindCandidats(IplImage * FaceImage);
};
inline void ReallocImage(IplImage** ppImage, CvSize sz, long lChNum)
{
IplImage* pImage;
if( ppImage == NULL )
return;
pImage = *ppImage;
if( pImage != NULL )
{
if (pImage->width != sz.width || pImage->height != sz.height || pImage->nChannels != lChNum)
cvReleaseImage( &pImage );
}
if( pImage == NULL )
pImage = cvCreateImage( sz, IPL_DEPTH_8U, lChNum);
*ppImage = pImage;
}
////////////
//class RFaceTemplate
///////////
class BoostingFaceTemplate:public FaceTemplate
{
public:
inline BoostingFaceTemplate(long lNumber,CvRect rect);
~BoostingFaceTemplate() {};
};//class RFaceTemplate:public FaceTemplate
inline BoostingFaceTemplate::BoostingFaceTemplate(long lNumber,CvRect rect):FaceTemplate(lNumber)
{
long EyeWidth = rect.width/5;
long EyeHeight = EyeWidth;
CvRect LeftEyeRect = cvRect(rect.x + EyeWidth,rect.y + rect.height/2 - EyeHeight,EyeWidth,EyeHeight);
CvRect RightEyeRect = cvRect(rect.x + 3*EyeWidth,rect.y + rect.height/2 - EyeHeight,EyeWidth,EyeHeight);
CvRect MouthRect = cvRect(rect.x + 3*EyeWidth/2,rect.y + 3*rect.height/4 - EyeHeight/2,2*EyeWidth,EyeHeight);
CvRect * lpMouthRect = new CvRect();
*lpMouthRect = MouthRect;
m_lpFeaturesList[0].SetContour(lpMouthRect);
m_lpFeaturesList[0].SetWeight(1);
m_lpFeaturesList[0].SetFeature(true);
CvRect * lpLeftEyeRect = new CvRect();
*lpLeftEyeRect = LeftEyeRect;
m_lpFeaturesList[1].SetContour(lpLeftEyeRect);
m_lpFeaturesList[1].SetWeight(1);
m_lpFeaturesList[1].SetFeature(true);
CvRect * lpRightEyeRect = new CvRect();
*lpRightEyeRect = RightEyeRect;
m_lpFeaturesList[2].SetContour(lpRightEyeRect);
m_lpFeaturesList[2].SetWeight(1);
m_lpFeaturesList[2].SetFeature(true);
}//inline BoostingFaceTemplate::BoostingFaceTemplate(long lNumber,CvRect rect):FaceTemplate(lNumber)
#endif // !defined(AFX_FACEDETECTION_H__55865033_D8E5_4DD5_8925_34C2285BB1BE__INCLUDED_)

View File

@@ -0,0 +1,405 @@
/*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*/
#ifndef _CV_MATRIX_H_
#define _CV_MATRIX_H_
#define icvCopyVector( src, dst, len ) memcpy( (dst), (src), (len)*sizeof((dst)[0]))
#define icvSetZero( dst, len ) memset( (dst), 0, (len)*sizeof((dst)[0]))
#define icvCopyVector_32f( src, len, dst ) memcpy((dst),(src),(len)*sizeof(float))
#define icvSetZero_32f( dst, cols, rows ) memset((dst),0,(rows)*(cols)*sizeof(float))
#define icvCopyVector_64d( src, len, dst ) memcpy((dst),(src),(len)*sizeof(double))
#define icvSetZero_64d( dst, cols, rows ) memset((dst),0,(rows)*(cols)*sizeof(double))
#define icvCopyMatrix_32f( src, w, h, dst ) memcpy((dst),(src),(w)*(h)*sizeof(float))
#define icvCopyMatrix_64d( src, w, h, dst ) memcpy((dst),(src),(w)*(h)*sizeof(double))
#define icvCreateVector_32f( len ) (float*)cvAlloc( (len)*sizeof(float))
#define icvCreateVector_64d( len ) (double*)cvAlloc( (len)*sizeof(double))
#define icvCreateMatrix_32f( w, h ) (float*)cvAlloc( (w)*(h)*sizeof(float))
#define icvCreateMatrix_64d( w, h ) (double*)cvAlloc( (w)*(h)*sizeof(double))
#define icvDeleteVector( vec ) cvFree( &(vec) )
#define icvDeleteMatrix icvDeleteVector
#define icvAddMatrix_32f( src1, src2, dst, w, h ) \
icvAddVector_32f( (src1), (src2), (dst), (w)*(h))
#define icvSubMatrix_32f( src1, src2, dst, w, h ) \
icvSubVector_32f( (src1), (src2), (dst), (w)*(h))
#define icvNormVector_32f( src, len ) \
sqrt(icvDotProduct_32f( src, src, len ))
#define icvNormVector_64d( src, len ) \
sqrt(icvDotProduct_64d( src, src, len ))
#define icvDeleteMatrix icvDeleteVector
#define icvCheckVector_64f( ptr, len )
#define icvCheckVector_32f( ptr, len )
CV_INLINE double icvSum_32f( const float* src, int len )
{
double s = 0;
for( int i = 0; i < len; i++ ) s += src[i];
icvCheckVector_64f( &s, 1 );
return s;
}
CV_INLINE double icvDotProduct_32f( const float* src1, const float* src2, int len )
{
double s = 0;
for( int i = 0; i < len; i++ ) s += src1[i]*src2[i];
icvCheckVector_64f( &s, 1 );
return s;
}
CV_INLINE double icvDotProduct_64f( const double* src1, const double* src2, int len )
{
double s = 0;
for( int i = 0; i < len; i++ ) s += src1[i]*src2[i];
icvCheckVector_64f( &s, 1 );
return s;
}
CV_INLINE void icvMulVectors_32f( const float* src1, const float* src2,
float* dst, int len )
{
int i;
for( i = 0; i < len; i++ )
dst[i] = src1[i] * src2[i];
icvCheckVector_32f( dst, len );
}
CV_INLINE void icvMulVectors_64d( const double* src1, const double* src2,
double* dst, int len )
{
int i;
for( i = 0; i < len; i++ )
dst[i] = src1[i] * src2[i];
icvCheckVector_64f( dst, len );
}
CV_INLINE void icvAddVector_32f( const float* src1, const float* src2,
float* dst, int len )
{
int i;
for( i = 0; i < len; i++ )
dst[i] = src1[i] + src2[i];
icvCheckVector_32f( dst, len );
}
CV_INLINE void icvAddVector_64d( const double* src1, const double* src2,
double* dst, int len )
{
int i;
for( i = 0; i < len; i++ )
dst[i] = src1[i] + src2[i];
icvCheckVector_64f( dst, len );
}
CV_INLINE void icvSubVector_32f( const float* src1, const float* src2,
float* dst, int len )
{
int i;
for( i = 0; i < len; i++ )
dst[i] = src1[i] - src2[i];
icvCheckVector_32f( dst, len );
}
CV_INLINE void icvSubVector_64d( const double* src1, const double* src2,
double* dst, int len )
{
int i;
for( i = 0; i < len; i++ )
dst[i] = src1[i] - src2[i];
icvCheckVector_64f( dst, len );
}
#define icvAddMatrix_64d( src1, src2, dst, w, h ) \
icvAddVector_64d( (src1), (src2), (dst), (w)*(h))
#define icvSubMatrix_64d( src1, src2, dst, w, h ) \
icvSubVector_64d( (src1), (src2), (dst), (w)*(h))
CV_INLINE void icvSetIdentity_32f( float* dst, int w, int h )
{
int i, len = MIN( w, h );
icvSetZero_32f( dst, w, h );
for( i = 0; len--; i += w+1 )
dst[i] = 1.f;
}
CV_INLINE void icvSetIdentity_64d( double* dst, int w, int h )
{
int i, len = MIN( w, h );
icvSetZero_64d( dst, w, h );
for( i = 0; len--; i += w+1 )
dst[i] = 1.;
}
CV_INLINE void icvTrace_32f( const float* src, int w, int h, float* trace )
{
int i, len = MIN( w, h );
double sum = 0;
for( i = 0; len--; i += w+1 )
sum += src[i];
*trace = (float)sum;
icvCheckVector_64f( &sum, 1 );
}
CV_INLINE void icvTrace_64d( const double* src, int w, int h, double* trace )
{
int i, len = MIN( w, h );
double sum = 0;
for( i = 0; len--; i += w+1 )
sum += src[i];
*trace = sum;
icvCheckVector_64f( &sum, 1 );
}
CV_INLINE void icvScaleVector_32f( const float* src, float* dst,
int len, double scale )
{
int i;
for( i = 0; i < len; i++ )
dst[i] = (float)(src[i]*scale);
icvCheckVector_32f( dst, len );
}
CV_INLINE void icvScaleVector_64d( const double* src, double* dst,
int len, double scale )
{
int i;
for( i = 0; i < len; i++ )
dst[i] = src[i]*scale;
icvCheckVector_64f( dst, len );
}
CV_INLINE void icvTransposeMatrix_32f( const float* src, int w, int h, float* dst )
{
int i, j;
for( i = 0; i < w; i++ )
for( j = 0; j < h; j++ )
*dst++ = src[j*w + i];
icvCheckVector_32f( dst, w*h );
}
CV_INLINE void icvTransposeMatrix_64d( const double* src, int w, int h, double* dst )
{
int i, j;
for( i = 0; i < w; i++ )
for( j = 0; j < h; j++ )
*dst++ = src[j*w + i];
icvCheckVector_64f( dst, w*h );
}
CV_INLINE void icvDetMatrix3x3_64d( const double* mat, double* det )
{
#define m(y,x) mat[(y)*3 + (x)]
*det = m(0,0)*(m(1,1)*m(2,2) - m(1,2)*m(2,1)) -
m(0,1)*(m(1,0)*m(2,2) - m(1,2)*m(2,0)) +
m(0,2)*(m(1,0)*m(2,1) - m(1,1)*m(2,0));
#undef m
icvCheckVector_64f( det, 1 );
}
CV_INLINE void icvMulMatrix_32f( const float* src1, int w1, int h1,
const float* src2, int w2, int h2,
float* dst )
{
int i, j, k;
if( w1 != h2 )
{
assert(0);
return;
}
for( i = 0; i < h1; i++, src1 += w1, dst += w2 )
for( j = 0; j < w2; j++ )
{
double s = 0;
for( k = 0; k < w1; k++ )
s += src1[k]*src2[j + k*w2];
dst[j] = (float)s;
}
icvCheckVector_32f( dst, h1*w2 );
}
CV_INLINE void icvMulMatrix_64d( const double* src1, int w1, int h1,
const double* src2, int w2, int h2,
double* dst )
{
int i, j, k;
if( w1 != h2 )
{
assert(0);
return;
}
for( i = 0; i < h1; i++, src1 += w1, dst += w2 )
for( j = 0; j < w2; j++ )
{
double s = 0;
for( k = 0; k < w1; k++ )
s += src1[k]*src2[j + k*w2];
dst[j] = s;
}
icvCheckVector_64f( dst, h1*w2 );
}
#define icvTransformVector_32f( matr, src, dst, w, h ) \
icvMulMatrix_32f( matr, w, h, src, 1, w, dst )
#define icvTransformVector_64d( matr, src, dst, w, h ) \
icvMulMatrix_64d( matr, w, h, src, 1, w, dst )
#define icvScaleMatrix_32f( src, dst, w, h, scale ) \
icvScaleVector_32f( (src), (dst), (w)*(h), (scale) )
#define icvScaleMatrix_64d( src, dst, w, h, scale ) \
icvScaleVector_64d( (src), (dst), (w)*(h), (scale) )
#define icvDotProduct_64d icvDotProduct_64f
CV_INLINE void icvInvertMatrix_64d( double* A, int n, double* invA )
{
CvMat Am = cvMat( n, n, CV_64F, A );
CvMat invAm = cvMat( n, n, CV_64F, invA );
cvInvert( &Am, &invAm, CV_SVD );
}
CV_INLINE void icvMulTransMatrixR_64d( double* src, int width, int height, double* dst )
{
CvMat srcMat = cvMat( height, width, CV_64F, src );
CvMat dstMat = cvMat( width, width, CV_64F, dst );
cvMulTransposed( &srcMat, &dstMat, 1 );
}
CV_INLINE void icvMulTransMatrixL_64d( double* src, int width, int height, double* dst )
{
CvMat srcMat = cvMat( height, width, CV_64F, src );
CvMat dstMat = cvMat( height, height, CV_64F, dst );
cvMulTransposed( &srcMat, &dstMat, 0 );
}
CV_INLINE void icvMulTransMatrixR_32f( float* src, int width, int height, float* dst )
{
CvMat srcMat = cvMat( height, width, CV_32F, src );
CvMat dstMat = cvMat( width, width, CV_32F, dst );
cvMulTransposed( &srcMat, &dstMat, 1 );
}
CV_INLINE void icvMulTransMatrixL_32f( float* src, int width, int height, float* dst )
{
CvMat srcMat = cvMat( height, width, CV_32F, src );
CvMat dstMat = cvMat( height, height, CV_32F, dst );
cvMulTransposed( &srcMat, &dstMat, 0 );
}
CV_INLINE void icvCvt_32f_64d( const float* src, double* dst, int len )
{
int i;
for( i = 0; i < len; i++ )
dst[i] = src[i];
}
CV_INLINE void icvCvt_64d_32f( const double* src, float* dst, int len )
{
int i;
for( i = 0; i < len; i++ )
dst[i] = (float)src[i];
}
#endif/*_CV_MATRIX_H_*/
/* End of file. */

View File

@@ -0,0 +1,163 @@
/*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*/
#ifndef __CVVECTRACK_H__
#define __CVVECTRACK_H__
#include <string.h>
#include <math.h>
#include <time.h>
#include <stdio.h>
#undef max
#undef min
#define max(a,b) ((a)<(b) ? (b) : (a))
#define min(a,b) ((a)>(b) ? (a) : (b))
inline int pow2(int v)
{
return (v*v);
}
inline int operator == (const CvRect& r1, const CvRect& r2)
{
return (r1.x == r2.x) && (r1.y == r2.y) &&
(r1.width == r2.width) && (r1.height == r2.height);
}
inline int operator != (const CvRect& r1, const CvRect& r2)
{
return !(r1 == r2);
}
inline
int CmpPoints(const CvPoint& p1, const CvPoint& p2, int err)
{
/* Simakov: modify __max to max */
return (max(abs(p1.x - p2.x), abs(p1.y - p2.y)) < err);
}
inline
int PointInRect(const CvPoint& p, const CvRect& r)
{
return ((p.x > r.x) && (p.x < (r.x + r.width)) &&
(p.y > r.y) && (p.y < (r.y + r.height)));
}
inline
int RectInRect(const CvRect& r1, const CvRect& r2)
{
CvPoint plt = {r1.x, r1.y};
CvPoint prb = {r1.x + r1.width, r1.y + r1.height};
return (PointInRect(plt, r2) && PointInRect(prb, r2));
}
inline
CvRect Increase(const CvRect& r, int decr)
{
CvRect rect;
rect.x = r.x * decr;
rect.y = r.y * decr;
rect.width = r.width * decr;
rect.height = r.height * decr;
return rect;
}
inline
CvPoint Increase(const CvPoint& p, int decr)
{
CvPoint point;
point.x = p.x * decr;
point.y = p.y * decr;
return point;
}
inline
void Move(CvRect& r, int dx, int dy)
{
r.x += dx;
r.y += dy;
}
inline
void Move(CvPoint& p, int dx, int dy)
{
p.x += dx;
p.y += dy;
}
inline
void Extend(CvRect& r, int d)
{
r.x -= d;
r.y -= d;
r.width += 2*d;
r.height += 2*d;
}
inline
CvPoint Center(const CvRect& r)
{
CvPoint p;
p.x = r.x + r.width / 2;
p.y = r.y + r.height / 2;
return p;
}
inline void ReallocImage(IplImage** ppImage, CvSize sz, long lChNum)
{
IplImage* pImage;
if( ppImage == NULL )
return;
pImage = *ppImage;
if( pImage != NULL )
{
if (pImage->width != sz.width || pImage->height != sz.height || pImage->nChannels != lChNum)
cvReleaseImage( &pImage );
}
if( pImage == NULL )
pImage = cvCreateImage( sz, IPL_DEPTH_8U, lChNum);
*ppImage = pImage;
}
#endif //__VECTRACK_H__

298
modules/legacy/src/_vm.h Normal file
View File

@@ -0,0 +1,298 @@
/*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*/
#ifndef _CV_VM_H_
#define _CV_VM_H_
/*----------------------- Internal ViewMorphing Functions ------------------------------*/
/*======================================================================================*/
typedef struct CvMatrix4
{
float m[4][4];
}
CvMatrix4;
/* Scanline section. Find coordinates by fundamental matrix */
/* Epsilon and real zero */
#define EPSILON 1.e-4
//#define REAL_ZERO(x) ( (x) < EPSILON && (x) > -EPSILON)
#define REAL_ZERO(x) ( (x) < 1e-8 && (x) > -1e-8)
#define SIGN(x) ( (x)<0 ? -1:((x)>0?1:0 ) )
CvStatus icvMakeScanlinesLengths( int* scanlines,
int numlines,
int* lens);
/*=============================== PreWarp section ======================================*/
CV_INLINE int icvGetColor(uchar* valueRGB);
CvStatus icvFindRunsInOneImage(
int numLines, /* number of scanlines */
uchar* prewarp, /* prewarp image */
int* line_lens, /* line lengths in pixels */
int* runs, /* result runs */
int* num_runs);
/*================================ Morphing section ====================================*/
CvStatus icvMorphEpilines8uC3( uchar* first_pix, /* raster epiline from the first image */
uchar* second_pix, /* raster epiline from the second image */
uchar* dst_pix, /* raster epiline from the destination image */
/* (it's an output parameter) */
float alpha, /* relative position of camera */
int* first, /* first sequence of runs */
int first_runs, /* it's length */
int* second, /* second sequence of runs */
int second_runs,
int* first_corr, /* correspond information for the 1st seq */
int* second_corr,
int dst_len); /* correspond information for the 2nd seq */
/*========================== Dynamic correspond section ================================*/
CvStatus icvDynamicCorrespond( int* first, /* first sequence of runs */
/* s0|w0|s1|w1|...|s(n-1)|w(n-1)|sn */
int first_runs, /* number of runs */
int* second, /* second sequence of runs */
int second_runs,
int* first_corr, /* s0'|e0'|s1'|e1'|... */
int* second_corr );
/*============================= PostWarp Functions =====================================*/
CvStatus icvFetchLine8uC3R(
uchar* src, int src_step,
uchar* dst, int* dst_num,
CvSize src_size,
CvPoint start,
CvPoint end );
CvStatus icvDrawLine8uC3R(
uchar* src, int src_num,
uchar* dst, int dst_step,
CvSize dst_size,
CvPoint start,
CvPoint end );
/*============================== Fundamental Matrix Functions ==========================*/
CvStatus icvPoint7( int* points1,
int* points2,
double* F,
int* amount
);
CvStatus icvCubic( double a2, double a1,
double a0, double* squares );
double icvDet( double* M );
double icvMinor( double* M, int x, int y );
int
icvGaussMxN( double *A, double *B, int M, int N, double **solutions );
CvStatus
icvGetCoef( double *f1, double *f2, double *a2, double *a1, double *a0 );
/*================================= Scanlines Functions ================================*/
CvStatus icvGetCoefficient( CvMatrix3* matrix,
CvSize imgSize,
int* scanlines_1,
int* scanlines_2,
int* numlines);
CvStatus icvGetCoefficientDefault( CvMatrix3* matrix,
CvSize imgSize,
int* scanlines_1,
int* scanlines_2,
int* numlines);
CvStatus icvGetCoefficientStereo( CvMatrix3* matrix,
CvSize imgSize,
float* l_epipole,
float* r_epipole,
int* scanlines_1,
int* scanlines_2,
int* numlines
);
CvStatus icvGetCoefficientOrto( CvMatrix3* matrix,
CvSize imgSize,
int* scanlines_1,
int* scanlines_2,
int* numlines);
CvStatus icvGetCrossEpilineFrame( CvSize imgSize,
float* epiline,
int* x1,
int* y1,
int* x2,
int* y2
);
CvStatus icvBuildScanlineLeftStereo(
CvSize imgSize,
CvMatrix3* matrix,
float* l_epipole,
float* l_angle,
float l_radius,
int* scanlines_1,
int* scanlines_2,
int* numlines);
CvStatus icvBuildScanlineRightStereo(
CvSize imgSize,
CvMatrix3* matrix,
float* r_epipole,
float* r_angle,
float r_radius,
int* scanlines_1,
int* scanlines_2,
int* numlines);
CvStatus icvGetStartEnd1(
CvMatrix3* matrix,
CvSize imgSize,
float* l_start_end,
float* r_start_end );
CvStatus icvGetStartEnd2(
CvMatrix3* matrix,
CvSize imgSize,
float* l_start_end,
float* r_start_end );
CvStatus icvGetStartEnd3(
CvMatrix3* matrix,
CvSize imgSize,
float* l_start_end,
float* r_start_end );
CvStatus icvGetStartEnd4(
CvMatrix3* matrix,
CvSize imgSize,
float* l_start_end,
float* r_start_end );
CvStatus icvBuildScanlineLeft(
CvMatrix3* matrix,
CvSize imgSize,
int* scanlines_1,
int* scanlines_2,
float* l_start_end,
int* numlines
);
CvStatus icvBuildScanlineRight(
CvMatrix3* matrix,
CvSize imgSize,
int* scanlines_1,
int* scanlines_2,
float* r_start_end,
int* numlines
);
/*=================================== LMedS Functions ==================================*/
CvStatus icvLMedS7(
int* points1,
int* points2,
CvMatrix3* matrix);
CvStatus icvLMedS( int* points1,
int* points2,
int numPoints,
CvMatrix3* fundamentalMatrix );
/*
CvStatus icvFindFundamentalMatrix(
int* points1,
int* points2,
int numpoints,
int method,
CvMatrix3* matrix);
*/
void icvChoose7( int* ml, int* mr,
int num, int* ml7,
int* mr7 );
double icvMedian( int* ml, int* mr,
int num, double* F );
int icvBoltingPoints( int* ml, int* mr,
int num, double* F,
double Mj, int* *new_ml,
int* *new_mr, int* new_num);
CvStatus icvPoints8( int* ml, int* mr,
int num, double* F );
CvStatus icvRank2Constraint( double* F );
CvStatus icvSort( double* array, int length );
double icvAnalyticPoints8( double* A,
int num, double* F );
int icvSingularValueDecomposition( int M,
int N,
double* A,
double* W,
int get_U,
double* U,
int get_V,
double* V
);
/*======================================================================================*/
#endif/*_CV_VM_H_*/

View File

@@ -0,0 +1,44 @@
/*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"
/* End of file. */

View File

@@ -0,0 +1,114 @@
/*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"
/****************************************************************************************\
calculate image homography
\****************************************************************************************/
CV_IMPL void
cvCalcImageHomography( float* line, CvPoint3D32f* _center,
float* _intrinsic, float* _homography )
{
double norm_xy, norm_xz, xy_sina, xy_cosa, xz_sina, xz_cosa, nx1, plane_dist;
float _ry[3], _rz[3], _r_trans[9];
CvMat rx = cvMat( 1, 3, CV_32F, line );
CvMat ry = cvMat( 1, 3, CV_32F, _ry );
CvMat rz = cvMat( 1, 3, CV_32F, _rz );
CvMat r_trans = cvMat( 3, 3, CV_32F, _r_trans );
CvMat center = cvMat( 3, 1, CV_32F, _center );
float _sub[9];
CvMat sub = cvMat( 3, 3, CV_32F, _sub );
float _t_trans[3];
CvMat t_trans = cvMat( 3, 1, CV_32F, _t_trans );
CvMat intrinsic = cvMat( 3, 3, CV_32F, _intrinsic );
CvMat homography = cvMat( 3, 3, CV_32F, _homography );
if( !line || !_center || !_intrinsic || !_homography )
CV_Error( CV_StsNullPtr, "" );
norm_xy = cvSqrt( line[0] * line[0] + line[1] * line[1] );
xy_cosa = line[0] / norm_xy;
xy_sina = line[1] / norm_xy;
norm_xz = cvSqrt( line[0] * line[0] + line[2] * line[2] );
xz_cosa = line[0] / norm_xz;
xz_sina = line[2] / norm_xz;
nx1 = -xz_sina;
_rz[0] = (float)(xy_cosa * nx1);
_rz[1] = (float)(xy_sina * nx1);
_rz[2] = (float)xz_cosa;
cvScale( &rz, &rz, 1./cvNorm(&rz,0,CV_L2) );
/* new axe y */
cvCrossProduct( &rz, &rx, &ry );
cvScale( &ry, &ry, 1./cvNorm( &ry, 0, CV_L2 ) );
/* transpone rotation matrix */
memcpy( &_r_trans[0], line, 3*sizeof(float));
memcpy( &_r_trans[3], _ry, 3*sizeof(float));
memcpy( &_r_trans[6], _rz, 3*sizeof(float));
/* calculate center distanse from arm plane */
plane_dist = cvDotProduct( &center, &rz );
/* calculate (I - r_trans)*center */
cvSetIdentity( &sub );
cvSub( &sub, &r_trans, &sub );
cvMatMul( &sub, &center, &t_trans );
cvMatMul( &t_trans, &rz, &sub );
cvScaleAdd( &sub, cvRealScalar(1./plane_dist), &r_trans, &sub ); /* ? */
cvMatMul( &intrinsic, &sub, &r_trans );
cvInvert( &intrinsic, &sub, CV_SVD );
cvMatMul( &r_trans, &sub, &homography );
}
/* End of file. */

View File

@@ -0,0 +1,923 @@
/*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 <stdio.h>
#undef quad
#if _MSC_VER >= 1200
#pragma warning( disable: 4701 )
#endif
CvCalibFilter::CvCalibFilter()
{
/* etalon data */
etalonType = CV_CALIB_ETALON_USER;
etalonParamCount = 0;
etalonParams = 0;
etalonPointCount = 0;
etalonPoints = 0;
/* camera data */
cameraCount = 1;
memset( points, 0, sizeof(points));
memset( undistMap, 0, sizeof(undistMap));
undistImg = 0;
memset( latestCounts, 0, sizeof(latestCounts));
memset( latestPoints, 0, sizeof(latestPoints));
memset( &stereo, 0, sizeof(stereo) );
maxPoints = 0;
framesTotal = 15;
framesAccepted = 0;
isCalibrated = false;
imgSize = cvSize(0,0);
grayImg = 0;
tempImg = 0;
storage = 0;
memset( rectMap, 0, sizeof(rectMap));
}
CvCalibFilter::~CvCalibFilter()
{
SetCameraCount(0);
cvFree( &etalonParams );
cvFree( &etalonPoints );
cvReleaseMat( &grayImg );
cvReleaseMat( &tempImg );
cvReleaseMat( &undistImg );
cvReleaseMemStorage( &storage );
}
bool CvCalibFilter::SetEtalon( CvCalibEtalonType type, double* params,
int pointCount, CvPoint2D32f* points )
{
int i, arrSize;
Stop();
if (latestPoints != NULL)
{
for( i = 0; i < MAX_CAMERAS; i++ )
cvFree( latestPoints + i );
}
if( type == CV_CALIB_ETALON_USER || type != etalonType )
{
if (etalonParams != NULL)
{
cvFree( &etalonParams );
}
}
etalonType = type;
switch( etalonType )
{
case CV_CALIB_ETALON_CHESSBOARD:
etalonParamCount = 3;
if( !params || cvRound(params[0]) != params[0] || params[0] < 3 ||
cvRound(params[1]) != params[1] || params[1] < 3 || params[2] <= 0 )
{
assert(0);
return false;
}
pointCount = cvRound((params[0] - 1)*(params[1] - 1));
break;
case CV_CALIB_ETALON_USER:
etalonParamCount = 0;
if( !points || pointCount < 4 )
{
assert(0);
return false;
}
break;
default:
assert(0);
return false;
}
if( etalonParamCount > 0 )
{
arrSize = etalonParamCount * sizeof(etalonParams[0]);
etalonParams = (double*)cvAlloc( arrSize );
}
arrSize = pointCount * sizeof(etalonPoints[0]);
if( etalonPointCount != pointCount )
{
if (etalonPoints != NULL)
{
cvFree( &etalonPoints );
}
etalonPointCount = pointCount;
etalonPoints = (CvPoint2D32f*)cvAlloc( arrSize );
}
switch( etalonType )
{
case CV_CALIB_ETALON_CHESSBOARD:
{
int etalonWidth = cvRound( params[0] ) - 1;
int etalonHeight = cvRound( params[1] ) - 1;
int x, y, k = 0;
etalonParams[0] = etalonWidth;
etalonParams[1] = etalonHeight;
etalonParams[2] = params[2];
for( y = 0; y < etalonHeight; y++ )
for( x = 0; x < etalonWidth; x++ )
{
etalonPoints[k++] = cvPoint2D32f( (etalonWidth - 1 - x)*params[2],
y*params[2] );
}
}
break;
case CV_CALIB_ETALON_USER:
if (params != NULL)
{
memcpy( etalonParams, params, arrSize );
}
if (points != NULL)
{
memcpy( etalonPoints, points, arrSize );
}
break;
default:
assert(0);
return false;
}
return true;
}
CvCalibEtalonType
CvCalibFilter::GetEtalon( int* paramCount, const double** params,
int* pointCount, const CvPoint2D32f** points ) const
{
if( paramCount )
*paramCount = etalonParamCount;
if( params )
*params = etalonParams;
if( pointCount )
*pointCount = etalonPointCount;
if( points )
*points = etalonPoints;
return etalonType;
}
void CvCalibFilter::SetCameraCount( int count )
{
Stop();
if( count != cameraCount )
{
for( int i = 0; i < cameraCount; i++ )
{
cvFree( points + i );
cvFree( latestPoints + i );
cvReleaseMat( &undistMap[i][0] );
cvReleaseMat( &undistMap[i][1] );
cvReleaseMat( &rectMap[i][0] );
cvReleaseMat( &rectMap[i][1] );
}
memset( latestCounts, 0, sizeof(latestPoints) );
maxPoints = 0;
cameraCount = count;
}
}
bool CvCalibFilter::SetFrames( int frames )
{
if( frames < 5 )
{
assert(0);
return false;
}
framesTotal = frames;
return true;
}
void CvCalibFilter::Stop( bool calibrate )
{
int i, j;
isCalibrated = false;
// deallocate undistortion maps
for( i = 0; i < cameraCount; i++ )
{
cvReleaseMat( &undistMap[i][0] );
cvReleaseMat( &undistMap[i][1] );
cvReleaseMat( &rectMap[i][0] );
cvReleaseMat( &rectMap[i][1] );
}
if( calibrate && framesAccepted > 0 )
{
int n = framesAccepted;
CvPoint3D32f* buffer =
(CvPoint3D32f*)cvAlloc( n * etalonPointCount * sizeof(buffer[0]));
CvMat mat;
float* rotMatr = (float*)cvAlloc( n * 9 * sizeof(rotMatr[0]));
float* transVect = (float*)cvAlloc( n * 3 * sizeof(transVect[0]));
int* counts = (int*)cvAlloc( n * sizeof(counts[0]));
cvInitMatHeader( &mat, 1, sizeof(CvCamera)/sizeof(float), CV_32FC1, 0 );
memset( cameraParams, 0, cameraCount * sizeof(cameraParams[0]));
for( i = 0; i < framesAccepted; i++ )
{
counts[i] = etalonPointCount;
for( j = 0; j < etalonPointCount; j++ )
buffer[i * etalonPointCount + j] = cvPoint3D32f( etalonPoints[j].x,
etalonPoints[j].y, 0 );
}
for( i = 0; i < cameraCount; i++ )
{
cvCalibrateCamera( framesAccepted, counts,
imgSize, points[i], buffer,
cameraParams[i].distortion,
cameraParams[i].matrix,
transVect, rotMatr, 0 );
cameraParams[i].imgSize[0] = (float)imgSize.width;
cameraParams[i].imgSize[1] = (float)imgSize.height;
// cameraParams[i].focalLength[0] = cameraParams[i].matrix[0];
// cameraParams[i].focalLength[1] = cameraParams[i].matrix[4];
// cameraParams[i].principalPoint[0] = cameraParams[i].matrix[2];
// cameraParams[i].principalPoint[1] = cameraParams[i].matrix[5];
memcpy( cameraParams[i].rotMatr, rotMatr, 9 * sizeof(rotMatr[0]));
memcpy( cameraParams[i].transVect, transVect, 3 * sizeof(transVect[0]));
mat.data.ptr = (uchar*)(cameraParams + i);
/* check resultant camera parameters: if there are some INF's or NAN's,
stop and reset results */
if( !cvCheckArr( &mat, CV_CHECK_RANGE | CV_CHECK_QUIET, -10000, 10000 ))
break;
}
isCalibrated = i == cameraCount;
{/* calibrate stereo cameras */
if( cameraCount == 2 )
{
stereo.camera[0] = &cameraParams[0];
stereo.camera[1] = &cameraParams[1];
icvStereoCalibration( framesAccepted, counts,
imgSize,
points[0],points[1],
buffer,
&stereo);
for( i = 0; i < 9; i++ )
{
stereo.fundMatr[i] = stereo.fundMatr[i];
}
}
}
cvFree( &buffer );
cvFree( &counts );
cvFree( &rotMatr );
cvFree( &transVect );
}
framesAccepted = 0;
}
bool CvCalibFilter::FindEtalon( IplImage** imgs )
{
return FindEtalon( (CvMat**)imgs );
}
bool CvCalibFilter::FindEtalon( CvMat** mats )
{
bool result = true;
if( !mats || etalonPointCount == 0 )
{
assert(0);
result = false;
}
if( result )
{
int i, tempPointCount0 = etalonPointCount*2;
for( i = 0; i < cameraCount; i++ )
{
if( !latestPoints[i] )
latestPoints[i] = (CvPoint2D32f*)
cvAlloc( tempPointCount0*2*sizeof(latestPoints[0]));
}
for( i = 0; i < cameraCount; i++ )
{
CvSize size;
int tempPointCount = tempPointCount0;
bool found = false;
if( !CV_IS_MAT(mats[i]) && !CV_IS_IMAGE(mats[i]))
{
assert(0);
break;
}
size = cvGetSize(mats[i]);
if( size.width != imgSize.width || size.height != imgSize.height )
{
imgSize = size;
}
if( !grayImg || grayImg->width != imgSize.width ||
grayImg->height != imgSize.height )
{
cvReleaseMat( &grayImg );
cvReleaseMat( &tempImg );
grayImg = cvCreateMat( imgSize.height, imgSize.width, CV_8UC1 );
tempImg = cvCreateMat( imgSize.height, imgSize.width, CV_8UC1 );
}
if( !storage )
storage = cvCreateMemStorage();
switch( etalonType )
{
case CV_CALIB_ETALON_CHESSBOARD:
if( CV_MAT_CN(cvGetElemType(mats[i])) == 1 )
cvCopy( mats[i], grayImg );
else
cvCvtColor( mats[i], grayImg, CV_BGR2GRAY );
found = cvFindChessBoardCornerGuesses( grayImg, tempImg, storage,
cvSize( cvRound(etalonParams[0]),
cvRound(etalonParams[1])),
latestPoints[i], &tempPointCount ) != 0;
if( found )
cvFindCornerSubPix( grayImg, latestPoints[i], tempPointCount,
cvSize(5,5), cvSize(-1,-1),
cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,10,0.1));
break;
default:
assert(0);
result = false;
break;
}
latestCounts[i] = found ? tempPointCount : -tempPointCount;
result = result && found;
}
}
if( storage )
cvClearMemStorage( storage );
return result;
}
bool CvCalibFilter::Push( const CvPoint2D32f** pts )
{
bool result = true;
int i, newMaxPoints = etalonPointCount*(MAX(framesAccepted,framesTotal) + 1);
isCalibrated = false;
if( !pts )
{
for( i = 0; i < cameraCount; i++ )
if( latestCounts[i] <= 0 )
return false;
pts = (const CvPoint2D32f**)latestPoints;
}
for( i = 0; i < cameraCount; i++ )
{
if( !pts[i] )
{
assert(0);
break;
}
if( maxPoints < newMaxPoints )
{
CvPoint2D32f* prev = points[i];
cvFree( points + i );
points[i] = (CvPoint2D32f*)cvAlloc( newMaxPoints * sizeof(prev[0]));
memcpy( points[i], prev, maxPoints * sizeof(prev[0]));
}
memcpy( points[i] + framesAccepted*etalonPointCount, pts[i],
etalonPointCount*sizeof(points[0][0]));
}
if( maxPoints < newMaxPoints )
maxPoints = newMaxPoints;
result = i == cameraCount;
if( ++framesAccepted >= framesTotal )
Stop( true );
return result;
}
bool CvCalibFilter::GetLatestPoints( int idx, CvPoint2D32f** pts,
int* count, bool* found )
{
int n;
if( (unsigned)idx >= (unsigned)cameraCount ||
!pts || !count || !found )
{
assert(0);
return false;
}
n = latestCounts[idx];
*found = n > 0;
*count = abs(n);
*pts = latestPoints[idx];
return true;
}
void CvCalibFilter::DrawPoints( IplImage** dst )
{
DrawPoints( (CvMat**)dst );
}
void CvCalibFilter::DrawPoints( CvMat** dstarr )
{
int i, j;
if( !dstarr )
{
assert(0);
return;
}
if( latestCounts )
{
for( i = 0; i < cameraCount; i++ )
{
if( dstarr[i] && latestCounts[i] )
{
CvMat dst_stub, *dst;
int count = 0;
bool found = false;
CvPoint2D32f* pts = 0;
GetLatestPoints( i, &pts, &count, &found );
dst = cvGetMat( dstarr[i], &dst_stub );
static const CvScalar line_colors[] =
{
{{0,0,255}},
{{0,128,255}},
{{0,200,200}},
{{0,255,0}},
{{200,200,0}},
{{255,0,0}},
{{255,0,255}}
};
const int colorCount = sizeof(line_colors)/sizeof(line_colors[0]);
const int r = 4;
CvScalar color = line_colors[0];
CvPoint prev_pt = { 0, 0};
for( j = 0; j < count; j++ )
{
CvPoint pt;
pt.x = cvRound(pts[j].x);
pt.y = cvRound(pts[j].y);
if( found )
{
if( etalonType == CV_CALIB_ETALON_CHESSBOARD )
color = line_colors[(j/cvRound(etalonParams[0]))%colorCount];
else
color = CV_RGB(0,255,0);
if( j != 0 )
cvLine( dst, prev_pt, pt, color, 1, CV_AA );
}
cvLine( dst, cvPoint( pt.x - r, pt.y - r ),
cvPoint( pt.x + r, pt.y + r ), color, 1, CV_AA );
cvLine( dst, cvPoint( pt.x - r, pt.y + r),
cvPoint( pt.x + r, pt.y - r), color, 1, CV_AA );
cvCircle( dst, pt, r+1, color, 1, CV_AA );
prev_pt = pt;
}
}
}
}
}
/* Get total number of frames and already accepted pair of frames */
int CvCalibFilter::GetFrameCount( int* total ) const
{
if( total )
*total = framesTotal;
return framesAccepted;
}
/* Get camera parameters for specified camera. If camera is not calibrated
the function returns 0 */
const CvCamera* CvCalibFilter::GetCameraParams( int idx ) const
{
if( (unsigned)idx >= (unsigned)cameraCount )
{
assert(0);
return 0;
}
return isCalibrated ? cameraParams + idx : 0;
}
/* Get camera parameters for specified camera. If camera is not calibrated
the function returns 0 */
const CvStereoCamera* CvCalibFilter::GetStereoParams() const
{
if( !(isCalibrated && cameraCount == 2) )
{
assert(0);
return 0;
}
return &stereo;
}
/* Sets camera parameters for all cameras */
bool CvCalibFilter::SetCameraParams( CvCamera* params )
{
CvMat mat;
int arrSize;
Stop();
if( !params )
{
assert(0);
return false;
}
arrSize = cameraCount * sizeof(params[0]);
cvInitMatHeader( &mat, 1, cameraCount * (arrSize/sizeof(float)),
CV_32FC1, params );
cvCheckArr( &mat, CV_CHECK_RANGE, -10000, 10000 );
memcpy( cameraParams, params, arrSize );
isCalibrated = true;
return true;
}
bool CvCalibFilter::SaveCameraParams( const char* filename )
{
if( isCalibrated )
{
int i, j;
FILE* f = fopen( filename, "w" );
if( !f ) return false;
fprintf( f, "%d\n\n", cameraCount );
for( i = 0; i < cameraCount; i++ )
{
for( j = 0; j < (int)(sizeof(cameraParams[i])/sizeof(float)); j++ )
{
fprintf( f, "%15.10f ", ((float*)(cameraParams + i))[j] );
}
fprintf( f, "\n\n" );
}
/* Save stereo params */
/* Save quad */
for( i = 0; i < 2; i++ )
{
for( j = 0; j < 4; j++ )
{
fprintf(f, "%15.10f ", stereo.quad[i][j].x );
fprintf(f, "%15.10f ", stereo.quad[i][j].y );
}
fprintf(f, "\n");
}
/* Save coeffs */
for( i = 0; i < 2; i++ )
{
for( j = 0; j < 9; j++ )
{
fprintf(f, "%15.10lf ", stereo.coeffs[i][j/3][j%3] );
}
fprintf(f, "\n");
}
fclose(f);
return true;
}
return true;
}
bool CvCalibFilter::LoadCameraParams( const char* filename )
{
int i, j;
int d = 0;
FILE* f = fopen( filename, "r" );
isCalibrated = false;
if( !f ) return false;
if( fscanf( f, "%d", &d ) != 1 || d <= 0 || d > 10 )
return false;
SetCameraCount( d );
for( i = 0; i < cameraCount; i++ )
{
for( j = 0; j < (int)(sizeof(cameraParams[i])/sizeof(float)); j++ )
{
fscanf( f, "%f", &((float*)(cameraParams + i))[j] );
}
}
/* Load stereo params */
/* load quad */
for( i = 0; i < 2; i++ )
{
for( j = 0; j < 4; j++ )
{
fscanf(f, "%f ", &(stereo.quad[i][j].x) );
fscanf(f, "%f ", &(stereo.quad[i][j].y) );
}
}
/* Load coeffs */
for( i = 0; i < 2; i++ )
{
for( j = 0; j < 9; j++ )
{
fscanf(f, "%lf ", &(stereo.coeffs[i][j/3][j%3]) );
}
}
fclose(f);
stereo.warpSize = cvSize( cvRound(cameraParams[0].imgSize[0]), cvRound(cameraParams[0].imgSize[1]));
isCalibrated = true;
return true;
}
bool CvCalibFilter::Rectify( IplImage** srcarr, IplImage** dstarr )
{
return Rectify( (CvMat**)srcarr, (CvMat**)dstarr );
}
bool CvCalibFilter::Rectify( CvMat** srcarr, CvMat** dstarr )
{
int i;
if( !srcarr || !dstarr )
{
assert(0);
return false;
}
if( isCalibrated && cameraCount == 2 )
{
for( i = 0; i < cameraCount; i++ )
{
if( srcarr[i] && dstarr[i] )
{
IplImage src_stub, *src;
IplImage dst_stub, *dst;
src = cvGetImage( srcarr[i], &src_stub );
dst = cvGetImage( dstarr[i], &dst_stub );
if( src->imageData == dst->imageData )
{
if( !undistImg ||
undistImg->width != src->width ||
undistImg->height != src->height ||
CV_MAT_CN(undistImg->type) != src->nChannels )
{
cvReleaseMat( &undistImg );
undistImg = cvCreateMat( src->height, src->width,
CV_8U + (src->nChannels-1)*8 );
}
cvCopy( src, undistImg );
src = cvGetImage( undistImg, &src_stub );
}
cvZero( dst );
if( !rectMap[i][0] || rectMap[i][0]->width != src->width ||
rectMap[i][0]->height != src->height )
{
cvReleaseMat( &rectMap[i][0] );
cvReleaseMat( &rectMap[i][1] );
rectMap[i][0] = cvCreateMat(stereo.warpSize.height,stereo.warpSize.width,CV_32FC1);
rectMap[i][1] = cvCreateMat(stereo.warpSize.height,stereo.warpSize.width,CV_32FC1);
cvComputePerspectiveMap(stereo.coeffs[i], rectMap[i][0], rectMap[i][1]);
}
cvRemap( src, dst, rectMap[i][0], rectMap[i][1] );
}
}
}
else
{
for( i = 0; i < cameraCount; i++ )
{
if( srcarr[i] != dstarr[i] )
cvCopy( srcarr[i], dstarr[i] );
}
}
return true;
}
bool CvCalibFilter::Undistort( IplImage** srcarr, IplImage** dstarr )
{
return Undistort( (CvMat**)srcarr, (CvMat**)dstarr );
}
bool CvCalibFilter::Undistort( CvMat** srcarr, CvMat** dstarr )
{
int i;
if( !srcarr || !dstarr )
{
assert(0);
return false;
}
if( isCalibrated )
{
for( i = 0; i < cameraCount; i++ )
{
if( srcarr[i] && dstarr[i] )
{
CvMat src_stub, *src;
CvMat dst_stub, *dst;
src = cvGetMat( srcarr[i], &src_stub );
dst = cvGetMat( dstarr[i], &dst_stub );
if( src->data.ptr == dst->data.ptr )
{
if( !undistImg || undistImg->width != src->width ||
undistImg->height != src->height ||
CV_ARE_TYPES_EQ( undistImg, src ))
{
cvReleaseMat( &undistImg );
undistImg = cvCreateMat( src->height, src->width, src->type );
}
cvCopy( src, undistImg );
src = undistImg;
}
#if 1
{
CvMat A = cvMat( 3, 3, CV_32FC1, cameraParams[i].matrix );
CvMat k = cvMat( 1, 4, CV_32FC1, cameraParams[i].distortion );
if( !undistMap[i][0] || undistMap[i][0]->width != src->width ||
undistMap[i][0]->height != src->height )
{
cvReleaseMat( &undistMap[i][0] );
cvReleaseMat( &undistMap[i][1] );
undistMap[i][0] = cvCreateMat( src->height, src->width, CV_32FC1 );
undistMap[i][1] = cvCreateMat( src->height, src->width, CV_32FC1 );
cvInitUndistortMap( &A, &k, undistMap[i][0], undistMap[i][1] );
}
cvRemap( src, dst, undistMap[i][0], undistMap[i][1] );
#else
cvUndistort2( src, dst, &A, &k );
#endif
}
}
}
}
else
{
for( i = 0; i < cameraCount; i++ )
{
if( srcarr[i] != dstarr[i] )
cvCopy( srcarr[i], dstarr[i] );
}
}
return true;
}

View File

@@ -0,0 +1,285 @@
/*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"
CvCamShiftTracker::CvCamShiftTracker()
{
int i;
memset( &m_box, 0, sizeof(m_box));
memset( &m_comp, 0, sizeof(m_comp));
memset( m_color_planes, 0, sizeof(m_color_planes));
m_threshold = 0;
for( i = 0; i < CV_MAX_DIM; i++ )
{
m_min_ch_val[i] = 0;
m_max_ch_val[i] = 255;
m_hist_ranges[i] = m_hist_ranges_data[i];
m_hist_ranges[i][0] = 0.f;
m_hist_ranges[i][1] = 256.f;
}
m_hist = 0;
m_back_project = 0;
m_temp = 0;
m_mask = 0;
}
CvCamShiftTracker::~CvCamShiftTracker()
{
int i;
cvReleaseHist( &m_hist );
for( i = 0; i < CV_MAX_DIM; i++ )
cvReleaseImage( &m_color_planes[i] );
cvReleaseImage( &m_back_project );
cvReleaseImage( &m_temp );
cvReleaseImage( &m_mask );
}
void
CvCamShiftTracker::color_transform( const IplImage* image )
{
CvSize size = cvGetSize(image);
uchar* color_data = 0, *mask = 0;
uchar* planes[CV_MAX_DIM];
int x, color_step = 0, plane_step = 0, mask_step;
int dims[CV_MAX_DIM];
int i, n = get_hist_dims(dims);
assert( image->nChannels == 3 && m_hist != 0 );
if( !m_temp || !m_mask || !m_color_planes[0] || !m_color_planes[n-1] || !m_back_project ||
m_temp->width != size.width || m_temp->height != size.height ||
m_temp->nChannels != 3 )
{
cvReleaseImage( &m_temp );
m_temp = cvCreateImage( size, IPL_DEPTH_8U, 3 );
cvReleaseImage( &m_mask );
m_mask = cvCreateImage( size, IPL_DEPTH_8U, 1 );
cvReleaseImage( &m_back_project );
m_back_project = cvCreateImage( size, IPL_DEPTH_8U, 1 );
for( i = 0; i < CV_MAX_DIM; i++ )
{
cvReleaseImage( &m_color_planes[i] );
if( i < n )
m_color_planes[i] = cvCreateImage( size, IPL_DEPTH_8U, 1 );
}
}
cvCvtColor( image, m_temp, CV_BGR2HSV );
cvGetRawData( m_temp, &color_data, &color_step, &size );
cvGetRawData( m_mask, &mask, &mask_step, &size );
for( i = 0; i < n; i++ )
cvGetRawData( m_color_planes[i], &planes[i], &plane_step, &size );
for( ; size.height--; color_data += color_step, mask += mask_step )
{
for( x = 0; x < size.width; x++ )
{
int val0 = color_data[x*3];
int val1 = color_data[x*3+1];
int val2 = color_data[x*3+2];
if( m_min_ch_val[0] <= val0 && val0 <= m_max_ch_val[0] &&
m_min_ch_val[1] <= val1 && val1 <= m_max_ch_val[1] &&
m_min_ch_val[2] <= val2 && val2 <= m_max_ch_val[2] )
{
// hue is written to the 0-th plane, saturation - to the 1-st one,
// so 1d histogram will automagically correspond to hue-based tracking,
// 2d histogram - to saturation-based tracking.
planes[0][x] = (uchar)val0;
if( n > 1 )
planes[1][x] = (uchar)val1;
if( n > 2 )
planes[2][x] = (uchar)val2;
mask[x] = (uchar)255;
}
else
{
planes[0][x] = 0;
if( n > 1 )
planes[1][x] = 0;
if( n > 2 )
planes[2][x] = 0;
mask[x] = 0;
}
}
for( i = 0; i < n; i++ )
planes[i] += plane_step;
}
}
bool
CvCamShiftTracker::update_histogram( const IplImage* cur_frame )
{
float max_val = 0;
int i, dims;
if( m_comp.rect.width == 0 || m_comp.rect.height == 0 ||
m_hist == 0 )
{
assert(0);
return false;
}
color_transform(cur_frame);
dims = cvGetDims( m_hist->bins );
for( i = 0; i < dims; i++ )
cvSetImageROI( m_color_planes[i], m_comp.rect );
cvSetImageROI( m_mask, m_comp.rect );
cvSetHistBinRanges( m_hist, m_hist_ranges, 1 );
cvCalcHist( m_color_planes, m_hist, 0, m_mask );
for( i = 0; i < dims; i++ )
cvSetImageROI( m_color_planes[i], m_comp.rect );
for( i = 0; i < dims; i++ )
cvResetImageROI( m_color_planes[i] );
cvResetImageROI( m_mask );
cvGetMinMaxHistValue( m_hist, 0, &max_val );
cvScale( m_hist->bins, m_hist->bins, max_val ? 255. / max_val : 0. );
return max_val != 0;
}
void
CvCamShiftTracker::reset_histogram()
{
if( m_hist )
cvClearHist( m_hist );
}
bool
CvCamShiftTracker::track_object( const IplImage* cur_frame )
{
CvRect rect;
CvSize bp_size;
union
{
void** arr;
IplImage** img;
} u;
if( m_comp.rect.width == 0 || m_comp.rect.height == 0 ||
m_hist == 0 )
{
return false;
}
color_transform( cur_frame );
u.img = m_color_planes;
cvCalcArrBackProject( u.arr, m_back_project, m_hist );
cvAnd( m_back_project, m_mask, m_back_project );
rect = m_comp.rect;
bp_size = cvGetSize( m_back_project );
if( rect.x < 0 )
rect.x = 0;
if( rect.x + rect.width > bp_size.width )
rect.width = bp_size.width - rect.x;
if( rect.y < 0 )
rect.y = 0;
if( rect.y + rect.height > bp_size.height )
rect.height = bp_size.height - rect.y;
cvCamShift( m_back_project, rect,
cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ),
&m_comp, &m_box );
if( m_comp.rect.width == 0 || m_comp.rect.height == 0 )
m_comp.rect = rect; // do not allow tracker to loose the object
return m_comp.rect.width != 0 && m_comp.rect.height != 0;
}
bool
CvCamShiftTracker::set_hist_dims( int c_dims, int *dims )
{
if( (unsigned)(c_dims-1) >= (unsigned)CV_MAX_DIM || dims == 0 )
return false;
if( m_hist )
{
int dims2[CV_MAX_DIM];
int c_dims2 = cvGetDims( m_hist->bins, dims2 );
if( c_dims2 == c_dims && memcmp( dims, dims2, c_dims*sizeof(dims[0])) == 0 )
return true;
cvReleaseHist( &m_hist );
}
m_hist = cvCreateHist( c_dims, dims, CV_HIST_ARRAY, 0, 0 );
return true;
}
bool
CvCamShiftTracker::set_hist_bin_range( int channel, int min_val, int max_val )
{
if( (unsigned)channel >= (unsigned)CV_MAX_DIM ||
min_val >= max_val || min_val < 0 || max_val > 256 )
{
assert(0);
return false;
}
m_hist_ranges[channel][0] = (float)min_val;
m_hist_ranges[channel][1] = (float)max_val;
return true;
}
/* End of file. */

View File

@@ -0,0 +1,709 @@
/*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"
#if 0
#include <float.h>
#include <limits.h>
#include <stdio.h>
#include "_cvutils.h"
#include "_cvwrap.h"
/*typedef struct CvCliqueFinder
{
CvGraph* graph;
int** adj_matr;
int N; //graph size
// stacks, counters etc/
int k; //stack size
int* current_comp;
int** All;
int* ne;
int* ce;
int* fixp; //node with minimal disconnections
int* nod;
int* s; //for selected candidate
int status;
int best_score;
} CvCliqueFinder;
*/
#define GO 1
#define BACK 2
#define PEREBOR 3
#define NEXT PEREBOR
#define END 4
#define CV_GET_ADJ_VTX( vertex, edge ) \
( \
assert(edge->vtx[0]==vertex||edge->vtx[1] == vertex ), \
(edge->vtx[0] == vertex)?edge->vtx[1]:edge->vtx[0] \
)
#define NUMBER( v ) ((v)->flags >> 1 )
void _MarkNodes( CvGraph* graph )
{
//set number of vertices to their flags
for( int i = 0; i < graph->total; i++ )
{
CvGraphVtx* ver = cvGetGraphVtx( graph, i );
if( ver )
{
ver->flags = i<<1;
}
}
}
void _FillAdjMatrix( CvGraph* graph, int** connected, int reverse )
{
//assume all vertices are marked
for( int i = 0; i < graph->total; i++ )
{
for( int j = 0; j < graph->total; j++ )
{
connected[i][j] = 0|reverse;
}
//memset( connected[i], 0, sizeof(int)*graph->total );
CvGraphVtx* ver = cvGetGraphVtx( graph, i );
if( ver )
{
connected[i][i] = 1;
for( CvGraphEdge* e = ver->first; e ; e = CV_NEXT_GRAPH_EDGE( e, ver ) )
{
CvGraphVtx* v = CV_GET_ADJ_VTX( ver, e );
connected[i][NUMBER(v)] = 1^reverse;
}
}
}
}
void cvStartFindCliques( CvGraph* graph, CvCliqueFinder* finder, int reverse, int weighted, int weighted_edges )
{
int i;
if (weighted)
{
finder->weighted = 1;
finder->best_weight = 0;
finder->vertex_weights = (float*)malloc( sizeof(float)*(graph->total+1));
finder->cur_weight = (float*)malloc( sizeof(float)*(graph->total+1));
finder->cand_weight = (float*)malloc( sizeof(float)*(graph->total+1));
finder->cur_weight[0] = 0;
finder->cand_weight[0] = 0;
for( i = 0 ; i < graph->total; i++ )
{
CvGraphWeightedVtx* ver = (CvGraphWeightedVtx*)cvGetGraphVtx( graph, i );
assert(ver);
assert(ver->weight>=0);
finder->vertex_weights[i] = ver->weight;
finder->cand_weight[0] += ver->weight;
}
}
else finder->weighted = 0;
if (weighted_edges)
{
finder->weighted_edges = 1;
//finder->best_weight = 0;
finder->edge_weights = (float*)malloc( sizeof(float)*(graph->total)*(graph->total));
//finder->cur_weight = (float*)malloc( sizeof(float)*(graph->total+1));
//finder->cand_weight = (float*)malloc( sizeof(float)*(graph->total+1));
//finder->cur_weight[0] = 0;
//finder->cand_weight[0] = 0;
memset( finder->edge_weights, 0, sizeof(float)*(graph->total)*(graph->total) );
for( i = 0 ; i < graph->total; i++ )
{
CvGraphVtx* ver1 = cvGetGraphVtx( graph, i );
if(!ver1) continue;
for( int j = i ; j < graph->total; j++ )
{
CvGraphVtx* ver2 = cvGetGraphVtx( graph, j );
if(!ver2) continue;
CvGraphEdge* edge = cvFindGraphEdgeByPtr( graph, ver1, ver2 );
if( edge )
{
assert( ((CvGraphWeightedEdge*)edge)->weight >= 0 );
finder->edge_weights[ i * graph->total + j ] =
finder->edge_weights[ j * graph->total + i ] = ((CvGraphWeightedEdge*)edge)->weight;
}
}
}
}
else finder->weighted_edges = 0;
//int* Compsub; //current component (vertex stack)
finder->k = 0; //counter of steps
int N = finder->N = graph->total;
finder->current_comp = new int[N];
finder->All = new int*[N];
for( i = 0 ; i < finder->N; i++ )
{
finder->All[i] = new int[N];
}
finder->ne = new int[N+1];
finder->ce = new int[N+1];
finder->fixp = new int[N+1]; //node with minimal disconnections
finder->nod = new int[N+1];
finder->s = new int[N+1]; //for selected candidate
//form adj matrix
finder->adj_matr = new int*[N]; //assume filled with 0
for( i = 0 ; i < N; i++ )
{
finder->adj_matr[i] = new int[N];
}
//set number to vertices
_MarkNodes( graph );
_FillAdjMatrix( graph, finder->adj_matr, reverse );
//init all arrays
int k = finder->k = 0; //stack size
memset( finder->All[k], 0, sizeof(int) * N );
for( i = 0; i < N; i++ ) finder->All[k][i] = i;
finder->ne[0] = 0;
finder->ce[0] = N;
finder->status = GO;
finder->best_score = 0;
}
void cvEndFindCliques( CvCliqueFinder* finder )
{
int i;
//int* Compsub; //current component (vertex stack)
delete finder->current_comp;
for( i = 0 ; i < finder->N; i++ )
{
delete finder->All[i];
}
delete finder->All;
delete finder->ne;
delete finder->ce;
delete finder->fixp; //node with minimal disconnections
delete finder->nod;
delete finder->s; //for selected candidate
//delete adj matrix
for( i = 0 ; i < finder->N; i++ )
{
delete finder->adj_matr[i];
}
delete finder->adj_matr;
if(finder->weighted)
{
free(finder->vertex_weights);
free(finder->cur_weight);
free(finder->cand_weight);
}
if(finder->weighted_edges)
{
free(finder->edge_weights);
}
}
int cvFindNextMaximalClique( CvCliqueFinder* finder )
{
int** connected = finder->adj_matr;
// int N = finder->N; //graph size
// stacks, counters etc/
int k = finder->k; //stack size
int* Compsub = finder->current_comp;
int** All = finder->All;
int* ne = finder->ne;
int* ce = finder->ce;
int* fixp = finder->fixp; //node with minimal disconnections
int* nod = finder->nod;
int* s = finder->s; //for selected candidate
//START
while( k >= 0)
{
int* old = All[k];
switch(finder->status)
{
case GO://Forward step
/* we have all sets and will choose fixed point */
{
//check potential size of clique
if( (!finder->weighted) && (k + ce[k] - ne[k] < finder->best_score) )
{
finder->status = BACK;
break;
}
//check potential weight
if( finder->weighted && !finder->weighted_edges &&
finder->cur_weight[k] + finder->cand_weight[k] < finder->best_weight )
{
finder->status = BACK;
break;
}
int minnod = ce[k];
nod[k] = 0;
//for every vertex of All determine counter value and choose minimum
for( int i = 0; i < ce[k] && minnod != 0; i++)
{
int p = old[i]; //current point
int count = 0; //counter
int pos = 0;
/* Count disconnections with candidates */
for (int j = ne[k]; j < ce[k] && (count < minnod); j++)
{
if ( !connected[p][old[j]] )
{
count++;
/* Save position of potential candidate */
pos = j;
}
}
/* Test new minimum */
if (count < minnod)
{
fixp[k] = p; //set current point as fixed
minnod = count; //new value for minnod
if (i < ne[k]) //if current fixed point belongs to 'not'
{
s[k] = pos; //s - selected candidate
}
else
{
s[k] = i; //selected candidate is fixed point itself
/* preincr */
nod[k] = 1; //nod is aux variable, 1 means fixp == s
}
}
}//for
nod[k] = minnod + nod[k];
finder->status = NEXT;//go to backtrackcycle
}
break;
case NEXT:
//here we will look for candidate to translate into not
//s[k] now contains index of choosen candidate
{
int* new_ = All[k+1];
if( nod[k] != 0 )
{
//swap selected and first candidate
int i, p = old[s[k]];
old[s[k]] = old[ne[k]];
int sel = old[ne[k]] = p;
int newne = 0;
//fill new set 'not'
for ( i = 0; i < ne[k]; i++)
{
if (connected[sel][old[i]])
{
new_[newne] = old[i];
newne++;
}
}
//fill new set 'candidate'
int newce = newne;
i++;//skip selected candidate
float candweight = 0;
for (; i < ce[k]; i++)
{
if (connected[sel][old[i]])
{
new_[newce] = old[i];
if( finder->weighted )
candweight += finder->vertex_weights[old[i]];
newce++;
}
}
nod[k]--;
//add selected to stack
Compsub[k] = sel;
k++;
assert( k <= finder->N );
if( finder->weighted )
{
//update weights of current clique and candidates
finder->cur_weight[k] = finder->cur_weight[k-1] + finder->vertex_weights[sel];
finder->cand_weight[k] = candweight;
}
if( finder->weighted_edges )
{
//update total weight by edge weights
float added = 0;
for( int ind = 0; ind < k-1; ind++ )
{
added += finder->edge_weights[ Compsub[ind] * finder->N + sel ];
}
finder->cur_weight[k] += added;
}
//check if 'not' and 'cand' are both empty
if( newce == 0 )
{
finder->best_score = MAX(finder->best_score, k );
if( finder->weighted )
finder->best_weight = MAX( finder->best_weight, finder->cur_weight[k] );
/*FILE* file = fopen("cliques.txt", "a" );
for (int t=0; t<k; t++)
{
fprintf(file, "%d ", Compsub[t]);
}
fprintf(file, "\n");
fclose(file);
*/
//output new clique//************************
finder->status = BACK;
finder->k = k;
return CLIQUE_FOUND;
}
else //check nonempty set of candidates
if( newne < newce )
{
//go further
ne[k] = newne;
ce[k] = newce;
finder->status = GO;
break;
}
}
else
finder->status = BACK;
}
break;
case BACK:
{
//decrease stack
k--;
old = All[k];
if( k < 0 ) break;
//add to not
ne[k]++;
if( nod[k] > 0 )
{
//select next candidate
for( s[k] = ne[k]; s[k] < ce[k]; s[k]++ )
{
if( !connected[fixp[k]][old[s[k]]])
break;
}
assert( s[k] < ce[k] );
finder->status = NEXT;
}
else
finder->status = BACK;
}
break;
case END: assert(0);
}
}//end while
finder->status = END;
return CLIQUE_END;
}
void cvBronKerbosch( CvGraph* graph )
{
int* Compsub; //current component (vertex stack)
int k = 0; //counter of steps
int N = graph->total;
int i;
Compsub = new int[N];
int** All = new int*[N];
for( i = 0 ; i < N; i++ )
{
All[i] = new int[N];
}
int* ne = new int[N];
int* ce = new int[N];
int* fixp = new int[N]; //node with minimal disconnections
int* nod = new int[N];
int* s = new int[N]; //for selected candidate
//form adj matrix
int** connected = new int*[N]; //assume filled with 0
for( i = 0 ; i < N; i++ )
{
connected[i] = new int[N];
}
//set number to vertices
_MarkNodes( graph );
_FillAdjMatrix( graph, connected, 0 );
//init all arrays
k = 0; //stack size
memset( All[k], 0, sizeof(int) * N );
for( i = 0; i < N; i++ ) All[k][i] = i;
ne[0] = 0;
ce[0] = N;
int status = GO;
int best_score = 0;
//START
while( k >= 0)
{
int* old = All[k];
switch(status)
{
case GO://Forward step
/* we have all sets and will choose fixed point */
{
if( k + ce[k] - ne[k] < best_score )
{
status = BACK;
break;
}
int minnod = ce[k];
nod[k] = 0;
//for every vertex of All determine counter value and choose minimum
for( int i = 0; i < ce[k] && minnod != 0; i++)
{
int p = old[i]; //current point
int count = 0; //counter
int pos = 0;
/* Count disconnections with candidates */
for (int j = ne[k]; j < ce[k] && (count < minnod); j++)
{
if ( !connected[p][old[j]] )
{
count++;
/* Save position of potential candidate */
pos = j;
}
}
/* Test new minimum */
if (count < minnod)
{
fixp[k] = p; //set current point as fixed
minnod = count; //new value for minnod
if (i < ne[k]) //if current fixed point belongs to 'not'
{
s[k] = pos; //s - selected candidate
}
else
{
s[k] = i; //selected candidate is fixed point itself
/* preincr */
nod[k] = 1; //nod is aux variable, 1 means fixp == s
}
}
}//for
nod[k] = minnod + nod[k];
status = NEXT;//go to backtrackcycle
}
break;
case NEXT:
//here we will look for candidate to translate into not
//s[k] now contains index of choosen candidate
{
int* new_ = All[k+1];
if( nod[k] != 0 )
{
//swap selected and first candidate
int p = old[s[k]];
old[s[k]] = old[ne[k]];
int sel = old[ne[k]] = p;
int newne = 0;
//fill new set 'not'
for ( i = 0; i < ne[k]; i++)
{
if (connected[sel][old[i]])
{
new_[newne] = old[i];
newne++;
}
}
//fill new set 'candidate'
int newce = newne;
i++;//skip selected candidate
for (; i < ce[k]; i++)
{
if (connected[sel][old[i]])
{
new_[newce] = old[i];
newce++;
}
}
nod[k]--;
//add selected to stack
Compsub[k] = sel;
k++;
//check if 'not' and 'cand' are both empty
if( newce == 0 )
{
best_score = MAX(best_score, k );
FILE* file = fopen("cliques.txt", "a" );
for (int t=0; t<k; t++)
{
fprintf(file, "%d ", Compsub[t]);
}
fprintf(file, "\n");
fclose(file);
/*for( int t = 0; t < k; t++ )
{
printf("%d ", Compsub[t] );
}
printf("\n"); */
//printf("found %d\n", k);
//output new clique//************************
status = BACK;
}
else //check nonempty set of candidates
if( newne < newce )
{
//go further
ne[k] = newne;
ce[k] = newce;
status = GO;
break;
}
}
else
status = BACK;
}
break;
case BACK:
{
//decrease stack
k--;
old = All[k];
if( k < 0 ) break;
//add to not
ne[k]++;
if( nod[k] > 0 )
{
//select next candidate
for( s[k] = ne[k]; s[k] < ce[k]; s[k]++ )
{
if( !connected[fixp[k]][old[s[k]]])
break;
}
assert( s[k] < ce[k] );
status = NEXT;
}
else
status = BACK;
}
break;
}
}//end while
}//end cvBronKerbosch
#endif

View File

@@ -0,0 +1,264 @@
/*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"
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvCreateConDensation
// Purpose: Creating CvConDensation structure and allocating memory for it
// Context:
// Parameters:
// Kalman - double pointer to CvConDensation structure
// DP - dimension of the dynamical vector
// MP - dimension of the measurement vector
// SamplesNum - number of samples in sample set used in algorithm
// Returns:
// Notes:
//
//F*/
CV_IMPL CvConDensation* cvCreateConDensation( int DP, int MP, int SamplesNum )
{
int i;
CvConDensation *CD = 0;
if( DP < 0 || MP < 0 || SamplesNum < 0 )
CV_Error( CV_StsOutOfRange, "" );
/* allocating memory for the structure */
CD = (CvConDensation *) cvAlloc( sizeof( CvConDensation ));
/* setting structure params */
CD->SamplesNum = SamplesNum;
CD->DP = DP;
CD->MP = MP;
/* allocating memory for structure fields */
CD->flSamples = (float **) cvAlloc( sizeof( float * ) * SamplesNum );
CD->flNewSamples = (float **) cvAlloc( sizeof( float * ) * SamplesNum );
CD->flSamples[0] = (float *) cvAlloc( sizeof( float ) * SamplesNum * DP );
CD->flNewSamples[0] = (float *) cvAlloc( sizeof( float ) * SamplesNum * DP );
/* setting pointers in pointer's arrays */
for( i = 1; i < SamplesNum; i++ )
{
CD->flSamples[i] = CD->flSamples[i - 1] + DP;
CD->flNewSamples[i] = CD->flNewSamples[i - 1] + DP;
}
CD->State = (float *) cvAlloc( sizeof( float ) * DP );
CD->DynamMatr = (float *) cvAlloc( sizeof( float ) * DP * DP );
CD->flConfidence = (float *) cvAlloc( sizeof( float ) * SamplesNum );
CD->flCumulative = (float *) cvAlloc( sizeof( float ) * SamplesNum );
CD->RandS = (CvRandState *) cvAlloc( sizeof( CvRandState ) * DP );
CD->Temp = (float *) cvAlloc( sizeof( float ) * DP );
CD->RandomSample = (float *) cvAlloc( sizeof( float ) * DP );
/* Returning created structure */
return CD;
}
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvReleaseConDensation
// Purpose: Releases CvConDensation structure and frees memory allocated for it
// Context:
// Parameters:
// Kalman - double pointer to CvConDensation structure
// DP - dimension of the dynamical vector
// MP - dimension of the measurement vector
// SamplesNum - number of samples in sample set used in algorithm
// Returns:
// Notes:
//
//F*/
CV_IMPL void
cvReleaseConDensation( CvConDensation ** ConDensation )
{
CvConDensation *CD = *ConDensation;
if( !ConDensation )
CV_Error( CV_StsNullPtr, "" );
if( !CD )
return;
/* freeing the memory */
cvFree( &CD->State );
cvFree( &CD->DynamMatr);
cvFree( &CD->flConfidence );
cvFree( &CD->flCumulative );
cvFree( &CD->flSamples[0] );
cvFree( &CD->flNewSamples[0] );
cvFree( &CD->flSamples );
cvFree( &CD->flNewSamples );
cvFree( &CD->Temp );
cvFree( &CD->RandS );
cvFree( &CD->RandomSample );
/* release structure */
cvFree( ConDensation );
}
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvConDensUpdateByTime
// Purpose: Performing Time Update routine for ConDensation algorithm
// Context:
// Parameters:
// Kalman - pointer to CvConDensation structure
// Returns:
// Notes:
//
//F*/
CV_IMPL void
cvConDensUpdateByTime( CvConDensation * ConDens )
{
int i, j;
float Sum = 0;
if( !ConDens )
CV_Error( CV_StsNullPtr, "" );
/* Sets Temp to Zero */
icvSetZero_32f( ConDens->Temp, ConDens->DP, 1 );
/* Calculating the Mean */
for( i = 0; i < ConDens->SamplesNum; i++ )
{
icvScaleVector_32f( ConDens->flSamples[i], ConDens->State, ConDens->DP,
ConDens->flConfidence[i] );
icvAddVector_32f( ConDens->Temp, ConDens->State, ConDens->Temp, ConDens->DP );
Sum += ConDens->flConfidence[i];
ConDens->flCumulative[i] = Sum;
}
/* Taking the new vector from transformation of mean by dynamics matrix */
icvScaleVector_32f( ConDens->Temp, ConDens->Temp, ConDens->DP, 1.f / Sum );
icvTransformVector_32f( ConDens->DynamMatr, ConDens->Temp, ConDens->State, ConDens->DP,
ConDens->DP );
Sum = Sum / ConDens->SamplesNum;
/* Updating the set of random samples */
for( i = 0; i < ConDens->SamplesNum; i++ )
{
j = 0;
while( (ConDens->flCumulative[j] <= (float) i * Sum)&&(j<ConDens->SamplesNum-1))
{
j++;
}
icvCopyVector_32f( ConDens->flSamples[j], ConDens->DP, ConDens->flNewSamples[i] );
}
/* Adding the random-generated vector to every vector in sample set */
for( i = 0; i < ConDens->SamplesNum; i++ )
{
for( j = 0; j < ConDens->DP; j++ )
{
cvbRand( ConDens->RandS + j, ConDens->RandomSample + j, 1 );
}
icvTransformVector_32f( ConDens->DynamMatr, ConDens->flNewSamples[i],
ConDens->flSamples[i], ConDens->DP, ConDens->DP );
icvAddVector_32f( ConDens->flSamples[i], ConDens->RandomSample, ConDens->flSamples[i],
ConDens->DP );
}
}
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvConDensInitSamplSet
// Purpose: Performing Time Update routine for ConDensation algorithm
// Context:
// Parameters:
// conDens - pointer to CvConDensation structure
// lowerBound - vector of lower bounds used to random update of sample set
// lowerBound - vector of upper bounds used to random update of sample set
// Returns:
// Notes:
//
//F*/
CV_IMPL void
cvConDensInitSampleSet( CvConDensation * conDens, CvMat * lowerBound, CvMat * upperBound )
{
int i, j;
float *LBound;
float *UBound;
float Prob = 1.f / conDens->SamplesNum;
if( !conDens || !lowerBound || !upperBound )
CV_Error( CV_StsNullPtr, "" );
if( CV_MAT_TYPE(lowerBound->type) != CV_32FC1 ||
!CV_ARE_TYPES_EQ(lowerBound,upperBound) )
CV_Error( CV_StsBadArg, "source has not appropriate format" );
if( (lowerBound->cols != 1) || (upperBound->cols != 1) )
CV_Error( CV_StsBadArg, "source has not appropriate size" );
if( (lowerBound->rows != conDens->DP) || (upperBound->rows != conDens->DP) )
CV_Error( CV_StsBadArg, "source has not appropriate size" );
LBound = lowerBound->data.fl;
UBound = upperBound->data.fl;
/* Initializing the structures to create initial Sample set */
for( i = 0; i < conDens->DP; i++ )
{
cvRandInit( &(conDens->RandS[i]),
LBound[i],
UBound[i],
i );
}
/* Generating the samples */
for( j = 0; j < conDens->SamplesNum; j++ )
{
for( i = 0; i < conDens->DP; i++ )
{
cvbRand( conDens->RandS + i, conDens->flSamples[j] + i, 1 );
}
conDens->flConfidence[j] = Prob;
}
/* Reinitializes the structures to update samples randomly */
for( i = 0; i < conDens->DP; i++ )
{
cvRandInit( &(conDens->RandS[i]),
(LBound[i] - UBound[i]) / 5,
(UBound[i] - LBound[i]) / 5,
i);
}
}

View File

@@ -0,0 +1,972 @@
/*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"
#define _CV_BINTREE_LIST() \
struct _CvTrianAttr* prev_v; /* pointer to the parent element on the previous level of the tree */ \
struct _CvTrianAttr* next_v1; /* pointer to the child element on the next level of the tree */ \
struct _CvTrianAttr* next_v2; /* pointer to the child element on the next level of the tree */
typedef struct _CvTrianAttr
{
CvPoint pt; /* Coordinates x and y of the vertex which don't lie on the base line LMIAT */
char sign; /* sign of the triangle */
double area; /* area of the triangle */
double r1; /* The ratio of the height of triangle to the base of the triangle */
double r2; /* The ratio of the projection of the left side of the triangle on the base to the base */
_CV_BINTREE_LIST() /* structure double list */
}
_CvTrianAttr;
#define CV_MATCH_CHECK( status, cvFun ) \
{ \
status = cvFun; \
if( status != CV_OK ) \
goto M_END; \
}
static CvStatus
icvCalcTriAttr( const CvSeq * contour, CvPoint t2, CvPoint t1, int n1,
CvPoint t3, int n3, double *s, double *s_c,
double *h, double *a, double *b );
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: icvCreateContourTree
// Purpose:
// Create binary tree representation for the contour
// Context:
// Parameters:
// contour - pointer to input contour object.
// storage - pointer to the current storage block
// tree - output pointer to the binary tree representation
// threshold - threshold for the binary tree building
//
//F*/
static CvStatus
icvCreateContourTree( const CvSeq * contour, CvMemStorage * storage,
CvContourTree ** tree, double threshold )
{
CvPoint *pt_p; /* pointer to previos points */
CvPoint *pt_n; /* pointer to next points */
CvPoint *pt1, *pt2; /* pointer to current points */
CvPoint t, tp1, tp2, tp3, tn1, tn2, tn3;
int lpt, flag, i, j, i_tree, j_1, j_3, i_buf;
double s, sp1, sp2, sn1, sn2, s_c, sp1_c, sp2_c, sn1_c, sn2_c, h, hp1, hp2, hn1, hn2,
a, ap1, ap2, an1, an2, b, bp1, bp2, bn1, bn2;
double a_s_c, a_sp1_c;
_CvTrianAttr **ptr_p, **ptr_n, **ptr1, **ptr2; /* pointers to pointers of triangles */
_CvTrianAttr *cur_adr;
int *num_p, *num_n, *num1, *num2; /* numbers of input contour points */
int nm, nmp1, nmp2, nmp3, nmn1, nmn2, nmn3;
int seq_flags = 1, i_end, prev_null, prev2_null;
double koef = 1.5;
double eps = 1.e-7;
double e;
CvStatus status;
int hearder_size;
_CvTrianAttr tree_one, tree_two, *tree_end, *tree_root;
CvSeqWriter writer;
assert( contour != NULL && contour->total >= 4 );
status = CV_OK;
if( contour == NULL )
return CV_NULLPTR_ERR;
if( contour->total < 4 )
return CV_BADSIZE_ERR;
if( !CV_IS_SEQ_POINT_SET( contour ))
return CV_BADFLAG_ERR;
/* Convert Sequence to array */
lpt = contour->total;
pt_p = pt_n = NULL;
num_p = num_n = NULL;
ptr_p = ptr_n = ptr1 = ptr2 = NULL;
tree_end = NULL;
pt_p = (CvPoint *) cvAlloc( lpt * sizeof( CvPoint ));
pt_n = (CvPoint *) cvAlloc( lpt * sizeof( CvPoint ));
num_p = (int *) cvAlloc( lpt * sizeof( int ));
num_n = (int *) cvAlloc( lpt * sizeof( int ));
hearder_size = sizeof( CvContourTree );
seq_flags = CV_SEQ_POLYGON_TREE;
cvStartWriteSeq( seq_flags, hearder_size, sizeof( _CvTrianAttr ), storage, &writer );
ptr_p = (_CvTrianAttr **) cvAlloc( lpt * sizeof( _CvTrianAttr * ));
ptr_n = (_CvTrianAttr **) cvAlloc( lpt * sizeof( _CvTrianAttr * ));
memset( ptr_p, 0, lpt * sizeof( _CvTrianAttr * ));
memset( ptr_n, 0, lpt * sizeof( _CvTrianAttr * ));
if( pt_p == NULL || pt_n == NULL )
return CV_OUTOFMEM_ERR;
if( ptr_p == NULL || ptr_n == NULL )
return CV_OUTOFMEM_ERR;
/* write fild for the binary tree root */
/* start_writer = writer; */
tree_one.pt.x = tree_one.pt.y = 0;
tree_one.sign = 0;
tree_one.area = 0;
tree_one.r1 = tree_one.r2 = 0;
tree_one.next_v1 = tree_one.next_v2 = tree_one.prev_v = NULL;
CV_WRITE_SEQ_ELEM( tree_one, writer );
tree_root = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
if( cvCvtSeqToArray( contour, (char *) pt_p ) == (char *) contour )
return CV_BADPOINT_ERR;
for( i = 0; i < lpt; i++ )
num_p[i] = i;
i = lpt;
flag = 0;
i_tree = 0;
e = 20.; /* initial threshold value */
ptr1 = ptr_p;
ptr2 = ptr_n;
pt1 = pt_p;
pt2 = pt_n;
num1 = num_p;
num2 = num_n;
/* binary tree constraction */
while( i > 4 )
{
if( flag == 0 )
{
ptr1 = ptr_p;
ptr2 = ptr_n;
pt1 = pt_p;
pt2 = pt_n;
num1 = num_p;
num2 = num_n;
flag = 1;
}
else
{
ptr1 = ptr_n;
ptr2 = ptr_p;
pt1 = pt_n;
pt2 = pt_p;
num1 = num_n;
num2 = num_p;
flag = 0;
}
t = pt1[0];
nm = num1[0];
tp1 = pt1[i - 1];
nmp1 = num1[i - 1];
tp2 = pt1[i - 2];
nmp2 = num1[i - 2];
tp3 = pt1[i - 3];
nmp3 = num1[i - 3];
tn1 = pt1[1];
nmn1 = num1[1];
tn2 = pt1[2];
nmn2 = num1[2];
i_buf = 0;
i_end = -1;
CV_MATCH_CHECK( status,
icvCalcTriAttr( contour, t, tp1, nmp1, tn1, nmn1, &s, &s_c, &h, &a,
&b ));
CV_MATCH_CHECK( status,
icvCalcTriAttr( contour, tp1, tp2, nmp2, t, nm, &sp1, &sp1_c, &hp1,
&ap1, &bp1 ));
CV_MATCH_CHECK( status,
icvCalcTriAttr( contour, tp2, tp3, nmp3, tp1, nmp1, &sp2, &sp2_c, &hp2,
&ap2, &bp2 ));
CV_MATCH_CHECK( status,
icvCalcTriAttr( contour, tn1, t, nm, tn2, nmn2, &sn1, &sn1_c, &hn1,
&an1, &bn1 ));
j_3 = 3;
prev_null = prev2_null = 0;
for( j = 0; j < i; j++ )
{
tn3 = pt1[j_3];
nmn3 = num1[j_3];
if( j == 0 )
j_1 = i - 1;
else
j_1 = j - 1;
CV_MATCH_CHECK( status, icvCalcTriAttr( contour, tn2, tn1, nmn1, tn3, nmn3,
&sn2, &sn2_c, &hn2, &an2, &bn2 ));
if( (s_c < sp1_c && s_c < sp2_c && s_c <= sn1_c && s_c <= sn2_c && s_c < e) ||
(((s_c == sp1_c && s_c <= sp2_c) || (s_c == sp2_c && s_c <= sp1_c)) &&
s_c <= sn1_c && s_c <= sn2_c && s_c < e && j > 1 && prev2_null == 0) ||
(s_c < eps && j > 0 && prev_null == 0) )
{
prev_null = prev2_null = 1;
if( s_c < threshold )
{
if( ptr1[j_1] == NULL && ptr1[j] == NULL )
{
if( i_buf > 0 )
ptr2[i_buf - 1] = NULL;
else
i_end = 0;
}
else
{
/* form next vertex */
tree_one.pt = t;
tree_one.sign = (char) (CV_SIGN( s ));
tree_one.r1 = h / a;
tree_one.r2 = b / a;
tree_one.area = fabs( s );
tree_one.next_v1 = ptr1[j_1];
tree_one.next_v2 = ptr1[j];
CV_WRITE_SEQ_ELEM( tree_one, writer );
cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
if( ptr1[j_1] != NULL )
ptr1[j_1]->prev_v = cur_adr;
if( ptr1[j] != NULL )
ptr1[j]->prev_v = cur_adr;
if( i_buf > 0 )
ptr2[i_buf - 1] = cur_adr;
else
{
tree_end = (_CvTrianAttr *) writer.ptr;
i_end = 1;
}
i_tree++;
}
}
else
/* form next vertex */
{
tree_one.pt = t;
tree_one.sign = (char) (CV_SIGN( s ));
tree_one.area = fabs( s );
tree_one.r1 = h / a;
tree_one.r2 = b / a;
tree_one.next_v1 = ptr1[j_1];
tree_one.next_v2 = ptr1[j];
CV_WRITE_SEQ_ELEM( tree_one, writer );
cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
if( ptr1[j_1] != NULL )
ptr1[j_1]->prev_v = cur_adr;
if( ptr1[j] != NULL )
ptr1[j]->prev_v = cur_adr;
if( i_buf > 0 )
ptr2[i_buf - 1] = cur_adr;
else
{
tree_end = cur_adr;
i_end = 1;
}
i_tree++;
}
}
else
/* the current triangle is'not LMIAT */
{
prev_null = 0;
switch (prev2_null)
{
case 0:
break;
case 1:
{
prev2_null = 2;
break;
}
case 2:
{
prev2_null = 0;
break;
}
}
if( j != i - 1 || i_end == -1 )
ptr2[i_buf] = ptr1[j];
else if( i_end == 0 )
ptr2[i_buf] = NULL;
else
ptr2[i_buf] = tree_end;
pt2[i_buf] = t;
num2[i_buf] = num1[j];
i_buf++;
}
/* go to next vertex */
tp3 = tp2;
tp2 = tp1;
tp1 = t;
t = tn1;
tn1 = tn2;
tn2 = tn3;
nmp3 = nmp2;
nmp2 = nmp1;
nmp1 = nm;
nm = nmn1;
nmn1 = nmn2;
nmn2 = nmn3;
sp2 = sp1;
sp1 = s;
s = sn1;
sn1 = sn2;
sp2_c = sp1_c;
sp1_c = s_c;
s_c = sn1_c;
sn1_c = sn2_c;
ap2 = ap1;
ap1 = a;
a = an1;
an1 = an2;
bp2 = bp1;
bp1 = b;
b = bn1;
bn1 = bn2;
hp2 = hp1;
hp1 = h;
h = hn1;
hn1 = hn2;
j_3++;
if( j_3 >= i )
j_3 = 0;
}
i = i_buf;
e = e * koef;
}
/* constract tree root */
if( i != 4 )
return CV_BADFACTOR_ERR;
t = pt2[0];
tn1 = pt2[1];
tn2 = pt2[2];
tp1 = pt2[3];
nm = num2[0];
nmn1 = num2[1];
nmn2 = num2[2];
nmp1 = num2[3];
/* first pair of the triangles */
CV_MATCH_CHECK( status,
icvCalcTriAttr( contour, t, tp1, nmp1, tn1, nmn1, &s, &s_c, &h, &a, &b ));
CV_MATCH_CHECK( status,
icvCalcTriAttr( contour, tn2, tn1, nmn1, tp1, nmp1, &sn2, &sn2_c, &hn2,
&an2, &bn2 ));
/* second pair of the triangles */
CV_MATCH_CHECK( status,
icvCalcTriAttr( contour, tn1, t, nm, tn2, nmn2, &sn1, &sn1_c, &hn1, &an1,
&bn1 ));
CV_MATCH_CHECK( status,
icvCalcTriAttr( contour, tp1, tn2, nmn2, t, nm, &sp1, &sp1_c, &hp1, &ap1,
&bp1 ));
a_s_c = fabs( s_c - sn2_c );
a_sp1_c = fabs( sp1_c - sn1_c );
if( a_s_c > a_sp1_c )
/* form child vertexs for the root */
{
tree_one.pt = t;
tree_one.sign = (char) (CV_SIGN( s ));
tree_one.area = fabs( s );
tree_one.r1 = h / a;
tree_one.r2 = b / a;
tree_one.next_v1 = ptr2[3];
tree_one.next_v2 = ptr2[0];
tree_two.pt = tn2;
tree_two.sign = (char) (CV_SIGN( sn2 ));
tree_two.area = fabs( sn2 );
tree_two.r1 = hn2 / an2;
tree_two.r2 = bn2 / an2;
tree_two.next_v1 = ptr2[1];
tree_two.next_v2 = ptr2[2];
CV_WRITE_SEQ_ELEM( tree_one, writer );
cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
if( s_c > sn2_c )
{
if( ptr2[3] != NULL )
ptr2[3]->prev_v = cur_adr;
if( ptr2[0] != NULL )
ptr2[0]->prev_v = cur_adr;
ptr1[0] = cur_adr;
i_tree++;
CV_WRITE_SEQ_ELEM( tree_two, writer );
cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
if( ptr2[1] != NULL )
ptr2[1]->prev_v = cur_adr;
if( ptr2[2] != NULL )
ptr2[2]->prev_v = cur_adr;
ptr1[1] = cur_adr;
i_tree++;
pt1[0] = tp1;
pt1[1] = tn1;
}
else
{
CV_WRITE_SEQ_ELEM( tree_two, writer );
cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
if( ptr2[1] != NULL )
ptr2[1]->prev_v = cur_adr;
if( ptr2[2] != NULL )
ptr2[2]->prev_v = cur_adr;
ptr1[0] = cur_adr;
i_tree++;
CV_WRITE_SEQ_ELEM( tree_one, writer );
cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
if( ptr2[3] != NULL )
ptr2[3]->prev_v = cur_adr;
if( ptr2[0] != NULL )
ptr2[0]->prev_v = cur_adr;
ptr1[1] = cur_adr;
i_tree++;
pt1[0] = tn1;
pt1[1] = tp1;
}
}
else
{
tree_one.pt = tp1;
tree_one.sign = (char) (CV_SIGN( sp1 ));
tree_one.area = fabs( sp1 );
tree_one.r1 = hp1 / ap1;
tree_one.r2 = bp1 / ap1;
tree_one.next_v1 = ptr2[2];
tree_one.next_v2 = ptr2[3];
tree_two.pt = tn1;
tree_two.sign = (char) (CV_SIGN( sn1 ));
tree_two.area = fabs( sn1 );
tree_two.r1 = hn1 / an1;
tree_two.r2 = bn1 / an1;
tree_two.next_v1 = ptr2[0];
tree_two.next_v2 = ptr2[1];
CV_WRITE_SEQ_ELEM( tree_one, writer );
cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
if( sp1_c > sn1_c )
{
if( ptr2[2] != NULL )
ptr2[2]->prev_v = cur_adr;
if( ptr2[3] != NULL )
ptr2[3]->prev_v = cur_adr;
ptr1[0] = cur_adr;
i_tree++;
CV_WRITE_SEQ_ELEM( tree_two, writer );
cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
if( ptr2[0] != NULL )
ptr2[0]->prev_v = cur_adr;
if( ptr2[1] != NULL )
ptr2[1]->prev_v = cur_adr;
ptr1[1] = cur_adr;
i_tree++;
pt1[0] = tn2;
pt1[1] = t;
}
else
{
CV_WRITE_SEQ_ELEM( tree_two, writer );
cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
if( ptr2[0] != NULL )
ptr2[0]->prev_v = cur_adr;
if( ptr2[1] != NULL )
ptr2[1]->prev_v = cur_adr;
ptr1[0] = cur_adr;
i_tree++;
CV_WRITE_SEQ_ELEM( tree_one, writer );
cur_adr = (_CvTrianAttr *) (writer.ptr - writer.seq->elem_size);
if( ptr2[2] != NULL )
ptr2[2]->prev_v = cur_adr;
if( ptr2[3] != NULL )
ptr2[3]->prev_v = cur_adr;
ptr1[1] = cur_adr;
i_tree++;
pt1[0] = t;
pt1[1] = tn2;
}
}
/* form root */
s = cvContourArea( contour );
tree_root->pt = pt1[1];
tree_root->sign = 0;
tree_root->area = fabs( s );
tree_root->r1 = 0;
tree_root->r2 = 0;
tree_root->next_v1 = ptr1[0];
tree_root->next_v2 = ptr1[1];
tree_root->prev_v = NULL;
ptr1[0]->prev_v = (_CvTrianAttr *) tree_root;
ptr1[1]->prev_v = (_CvTrianAttr *) tree_root;
/* write binary tree root */
/* CV_WRITE_SEQ_ELEM (tree_one, start_writer); */
i_tree++;
/* create Sequence hearder */
*((CvSeq **) tree) = cvEndWriteSeq( &writer );
/* write points for the main segment into sequence header */
(*tree)->p1 = pt1[0];
M_END:
cvFree( &ptr_n );
cvFree( &ptr_p );
cvFree( &num_n );
cvFree( &num_p );
cvFree( &pt_n );
cvFree( &pt_p );
return status;
}
/****************************************************************************************\
triangle attributes calculations
\****************************************************************************************/
static CvStatus
icvCalcTriAttr( const CvSeq * contour, CvPoint t2, CvPoint t1, int n1,
CvPoint t3, int n3, double *s, double *s_c,
double *h, double *a, double *b )
{
double x13, y13, x12, y12, l_base, nx, ny, qq;
double eps = 1.e-5;
x13 = t3.x - t1.x;
y13 = t3.y - t1.y;
x12 = t2.x - t1.x;
y12 = t2.y - t1.y;
qq = x13 * x13 + y13 * y13;
l_base = cvSqrt( (float) (qq) );
if( l_base > eps )
{
nx = y13 / l_base;
ny = -x13 / l_base;
*h = nx * x12 + ny * y12;
*s = (*h) * l_base / 2.;
*b = nx * y12 - ny * x12;
*a = l_base;
/* calculate interceptive area */
*s_c = cvContourArea( contour, cvSlice(n1, n3+1));
}
else
{
*h = 0;
*s = 0;
*s_c = 0;
*b = 0;
*a = 0;
}
return CV_OK;
}
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvCreateContourTree
// Purpose:
// Create binary tree representation for the contour
// Context:
// Parameters:
// contour - pointer to input contour object.
// storage - pointer to the current storage block
// tree - output pointer to the binary tree representation
// threshold - threshold for the binary tree building
//
//F*/
CV_IMPL CvContourTree*
cvCreateContourTree( const CvSeq* contour, CvMemStorage* storage, double threshold )
{
CvContourTree* tree = 0;
IPPI_CALL( icvCreateContourTree( contour, storage, &tree, threshold ));
return tree;
}
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: icvContourFromContourTree
// Purpose:
// reconstracts contour from binary tree representation
// Context:
// Parameters:
// tree - pointer to the input binary tree representation
// storage - pointer to the current storage block
// contour - pointer to output contour object.
// criteria - criteria for the definition threshold value
// for the contour reconstracting (level or precision)
//F*/
CV_IMPL CvSeq*
cvContourFromContourTree( const CvContourTree* tree,
CvMemStorage* storage,
CvTermCriteria criteria )
{
CvSeq* contour = 0;
cv::AutoBuffer<_CvTrianAttr*> ptr_buf; /* pointer to the pointer's buffer */
cv::AutoBuffer<int> level_buf;
int i_buf;
int lpt;
double area_all;
double threshold;
int cur_level;
int level;
int seq_flags;
char log_iter, log_eps;
int out_hearder_size;
_CvTrianAttr *tree_one = 0, tree_root; /* current vertex */
CvSeqReader reader;
CvSeqWriter writer;
if( !tree )
CV_Error( CV_StsNullPtr, "" );
if( !CV_IS_SEQ_POLYGON_TREE( tree ))
CV_Error( CV_StsBadArg, "" );
criteria = cvCheckTermCriteria( criteria, 0., 100 );
lpt = tree->total;
ptr_buf = NULL;
level_buf = NULL;
i_buf = 0;
cur_level = 0;
log_iter = (char) (criteria.type == CV_TERMCRIT_ITER ||
(criteria.type == CV_TERMCRIT_ITER + CV_TERMCRIT_EPS));
log_eps = (char) (criteria.type == CV_TERMCRIT_EPS ||
(criteria.type == CV_TERMCRIT_ITER + CV_TERMCRIT_EPS));
cvStartReadSeq( (CvSeq *) tree, &reader, 0 );
out_hearder_size = sizeof( CvContour );
seq_flags = CV_SEQ_POLYGON;
cvStartWriteSeq( seq_flags, out_hearder_size, sizeof( CvPoint ), storage, &writer );
ptr_buf.allocate(lpt);
if( log_iter )
level_buf.allocate(lpt);
memset( ptr_buf, 0, lpt * sizeof( _CvTrianAttr * ));
/* write the first tree root's point as a start point of the result contour */
CV_WRITE_SEQ_ELEM( tree->p1, writer );
/* write the second tree root"s point into buffer */
/* read the root of the tree */
CV_READ_SEQ_ELEM( tree_root, reader );
tree_one = &tree_root;
area_all = tree_one->area;
if( log_eps )
threshold = criteria.epsilon * area_all;
else
threshold = 10 * area_all;
if( log_iter )
level = criteria.max_iter;
else
level = -1;
/* contour from binary tree constraction */
while( i_buf >= 0 )
{
if( tree_one != NULL && (cur_level <= level || tree_one->area >= threshold) )
/* go to left sub tree for the vertex and save pointer to the right vertex */
/* into the buffer */
{
ptr_buf[i_buf] = tree_one;
if( log_iter )
{
level_buf[i_buf] = cur_level;
cur_level++;
}
i_buf++;
tree_one = tree_one->next_v1;
}
else
{
i_buf--;
if( i_buf >= 0 )
{
CvPoint pt = ptr_buf[i_buf]->pt;
CV_WRITE_SEQ_ELEM( pt, writer );
tree_one = ptr_buf[i_buf]->next_v2;
if( log_iter )
{
cur_level = level_buf[i_buf] + 1;
}
}
}
}
contour = cvEndWriteSeq( &writer );
cvBoundingRect( contour, 1 );
return contour;
}
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: icvMatchContourTrees
// Purpose:
// Calculates matching of the two contour trees
// Context:
// Parameters:
// tree1 - pointer to the first input contour tree object.
// tree2 - pointer to the second input contour tree object.
// method - method for the matching calculation
// (now CV_CONTOUR_TREES_MATCH_I1 only )
// threshold - threshold for the contour trees matching
// result - output calculated measure
//F*/
CV_IMPL double
cvMatchContourTrees( const CvContourTree* tree1, const CvContourTree* tree2,
int method, double threshold )
{
cv::AutoBuffer<_CvTrianAttr*> buf;
_CvTrianAttr **ptr_p1 = 0, **ptr_p2 = 0; /*pointers to the pointer's buffer */
_CvTrianAttr **ptr_n1 = 0, **ptr_n2 = 0; /*pointers to the pointer's buffer */
_CvTrianAttr **ptr11, **ptr12, **ptr21, **ptr22;
int lpt1, lpt2, lpt, flag, flag_n, i, j, ibuf, ibuf1;
double match_v, d12, area1, area2, r11, r12, r21, r22, w1, w2;
double eps = 1.e-5;
char s1, s2;
_CvTrianAttr tree_1, tree_2; /*current vertex 1 and 2 tree */
CvSeqReader reader1, reader2;
if( !tree1 || !tree2 )
CV_Error( CV_StsNullPtr, "" );
if( method != CV_CONTOUR_TREES_MATCH_I1 )
CV_Error( CV_StsBadArg, "Unknown/unsupported comparison method" );
if( !CV_IS_SEQ_POLYGON_TREE( tree1 ))
CV_Error( CV_StsBadArg, "The first argument is not a valid contour tree" );
if( !CV_IS_SEQ_POLYGON_TREE( tree2 ))
CV_Error( CV_StsBadArg, "The second argument is not a valid contour tree" );
lpt1 = tree1->total;
lpt2 = tree2->total;
lpt = lpt1 > lpt2 ? lpt1 : lpt2;
ptr_p1 = ptr_n1 = ptr_p2 = ptr_n2 = NULL;
buf.allocate(lpt*4);
ptr_p1 = buf;
ptr_p2 = ptr_p1 + lpt;
ptr_n1 = ptr_p2 + lpt;
ptr_n2 = ptr_n1 + lpt;
cvStartReadSeq( (CvSeq *) tree1, &reader1, 0 );
cvStartReadSeq( (CvSeq *) tree2, &reader2, 0 );
/*read the root of the first and second tree*/
CV_READ_SEQ_ELEM( tree_1, reader1 );
CV_READ_SEQ_ELEM( tree_2, reader2 );
/*write to buffer pointers to root's childs vertexs*/
ptr_p1[0] = tree_1.next_v1;
ptr_p1[1] = tree_1.next_v2;
ptr_p2[0] = tree_2.next_v1;
ptr_p2[1] = tree_2.next_v2;
i = 2;
match_v = 0.;
area1 = tree_1.area;
area2 = tree_2.area;
if( area1 < eps || area2 < eps || lpt < 4 )
CV_Error( CV_StsBadSize, "" );
r11 = r12 = r21 = r22 = w1 = w2 = d12 = 0;
flag = 0;
s1 = s2 = 0;
do
{
if( flag == 0 )
{
ptr11 = ptr_p1;
ptr12 = ptr_n1;
ptr21 = ptr_p2;
ptr22 = ptr_n2;
flag = 1;
}
else
{
ptr11 = ptr_n1;
ptr12 = ptr_p1;
ptr21 = ptr_n2;
ptr22 = ptr_p2;
flag = 0;
}
ibuf = 0;
for( j = 0; j < i; j++ )
{
flag_n = 0;
if( ptr11[j] != NULL )
{
r11 = ptr11[j]->r1;
r12 = ptr11[j]->r2;
flag_n = 1;
w1 = ptr11[j]->area / area1;
s1 = ptr11[j]->sign;
}
else
{
r11 = r21 = 0;
}
if( ptr21[j] != NULL )
{
r21 = ptr21[j]->r1;
r22 = ptr21[j]->r2;
flag_n = 1;
w2 = ptr21[j]->area / area2;
s2 = ptr21[j]->sign;
}
else
{
r21 = r22 = 0;
}
if( flag_n != 0 )
/* calculate node distance */
{
switch (method)
{
case 1:
{
double t0, t1;
if( s1 != s2 )
{
t0 = fabs( r11 * w1 + r21 * w2 );
t1 = fabs( r12 * w1 + r22 * w2 );
}
else
{
t0 = fabs( r11 * w1 - r21 * w2 );
t1 = fabs( r12 * w1 - r22 * w2 );
}
d12 = t0 + t1;
break;
}
}
match_v += d12;
ibuf1 = ibuf + 1;
/*write to buffer the pointer to child vertexes*/
if( ptr11[j] != NULL )
{
ptr12[ibuf] = ptr11[j]->next_v1;
ptr12[ibuf1] = ptr11[j]->next_v2;
}
else
{
ptr12[ibuf] = NULL;
ptr12[ibuf1] = NULL;
}
if( ptr21[j] != NULL )
{
ptr22[ibuf] = ptr21[j]->next_v1;
ptr22[ibuf1] = ptr21[j]->next_v2;
}
else
{
ptr22[ibuf] = NULL;
ptr22[ibuf1] = NULL;
}
ibuf += 2;
}
}
i = ibuf;
}
while( i > 0 && match_v < threshold );
return match_v;
}

View File

@@ -0,0 +1,398 @@
/*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 "_vm.h"
#include <stdlib.h>
#include <assert.h>
/*======================================================================================*/
CvStatus
icvDynamicCorrespond( int *first, /* first sequence of runs */
/* s0|w0|s1|w1|...|s(n-1)|w(n-1)|sn */
int first_runs, /* number of runs */
int *second, /* second sequence of runs */
int second_runs, int *first_corr, /* s0'|e0'|s1'|e1'|... */
int *second_corr )
{
float Pd, Fi, S;
float Occlusion;
float *costTable;
uchar *matchEdges;
int prev;
int curr;
int baseIndex;
int i, j;
int i_1, j_1;
int n;
int l_beg, r_beg, l_end, r_end, l_len, r_len;
int first_curr;
int second_curr;
int l_color, r_color;
int len_color;
float cost, cost1;
float min1, min2, min3;
float cmin;
uchar cpath;
int row_size;
/* Test arguments for errors */
if( (first == 0) ||
(first_runs < 1) ||
(second == 0) || (second_runs < 1) || (first_corr == 0) || (second_corr == 0) )
return CV_BADFACTOR_ERR;
Pd = 0.95f;
Fi = (float) CV_PI;
S = 1;
Occlusion = (float) log( Pd * Fi / ((1 - Pd) * sqrt( fabs( (CV_PI * 2) * (1. / S) ))));
costTable = (float *)cvAlloc( (first_runs + 1) * (second_runs + 1) * sizeof( float ));
if( costTable == 0 )
return CV_OUTOFMEM_ERR;
matchEdges = (uchar *)cvAlloc( (first_runs + 1) * (second_runs + 1) * sizeof( uchar ));
if( matchEdges == 0 )
{
cvFree( &costTable );
return CV_OUTOFMEM_ERR;
}
row_size = first_runs + 1;
/* ============= Fill costTable ============= */
costTable[0] = 0.0f;
/* Fill upper line in the cost Table */
prev = first[0];
curr = 2;
for( n = 0; n < first_runs; n++ )
{
l_end = first[curr];
curr += 2;
costTable[n + 1] = costTable[n] + Occlusion * (l_end - prev);
prev = l_end;
} /* for */
/* Fill lefter line in the cost Table */
prev = second[0];
curr = 2;
baseIndex = 0;
for( n = 0; n < second_runs; n++ )
{
l_end = second[curr];
curr += 2;
costTable[baseIndex + row_size] = costTable[baseIndex] + Occlusion * (l_end - prev);
baseIndex += row_size;
prev = l_end;
} /* for */
/* Count costs in the all rest cells */
first_curr = 0;
second_curr = 0;
for( i = 1; i <= first_runs; i++ )
{
for( j = 1; j <= second_runs; j++ )
{
first_curr = (i - 1) * 2;
second_curr = (j - 1) * 2;
l_beg = first[first_curr];
first_curr++;
l_color = first[first_curr];
first_curr++;
l_end = first[first_curr];
l_len = l_end - l_beg + 1;
r_beg = second[second_curr];
second_curr++;
r_color = second[second_curr];
second_curr++;
r_end = second[second_curr];
r_len = r_end - r_beg + 1;
i_1 = i - 1;
j_1 = j - 1;
if( r_len == l_len )
{
cost = 0;
}
else
{
if( r_len > l_len )
{
cost = (float) (r_len * r_len - l_len * l_len) * (1 / (r_len * l_len));
}
else
{
cost = (float) (l_len * l_len - r_len * r_len) * (1 / (r_len * l_len));
}
} /* if */
len_color = r_color - l_color;
cost1 = (float) ((len_color * len_color) >> 2);
min2 = costTable[i_1 + j * row_size] + Occlusion * l_len;
min3 = costTable[i + j_1 * row_size] + Occlusion * r_len;
min1 = costTable[i_1 + j_1 * row_size] + cost + (float) cost1;
if( min1 < min2 )
{
if( min1 < min3 )
{
cmin = min1;
cpath = 1;
}
else
{
cmin = min3;
cpath = 3;
} /* if */
}
else
{
if( min2 < min3 )
{
cmin = min2;
cpath = 2;
}
else
{
cmin = min3;
cpath = 3;
} /* if */
} /* if */
costTable[i + j * row_size] = cmin;
matchEdges[i + j * row_size] = cpath;
} /* for */
} /* for */
/* =========== Reconstruct the Path =========== */
i = first_runs;
j = second_runs;
first_curr = i * 2 - 2;
second_curr = j * 2 - 2;
while( i > 0 && j > 0 )
{
/* Connect begins */
switch (matchEdges[i + j * row_size])
{
case 1: /* to diagonal */
first_corr[first_curr] = second[second_curr];
first_corr[first_curr + 1] = second[second_curr + 2];
second_corr[second_curr] = first[first_curr];
second_corr[second_curr + 1] = first[first_curr + 2];
first_curr -= 2;
second_curr -= 2;
i--;
j--;
break;
case 2: /* to left */
first_corr[first_curr] = second[second_curr + 2];
first_corr[first_curr + 1] = second[second_curr + 2];
first_curr -= 2;
i--;
break;
case 3: /* to up */
second_corr[second_curr] = first[first_curr + 2];
second_corr[second_curr + 1] = first[first_curr + 2];
second_curr -= 2;
j--;
break;
} /* switch */
} /* while */
/* construct rest of horisontal path if its need */
while( i > 0 )
{
first_corr[first_curr] = second[second_curr + 2]; /* connect to begin */
first_corr[first_curr + 1] = second[second_curr + 2]; /* connect to begin */
first_curr -= 2;
i--;
} /* while */
/* construct rest of vertical path if its need */
while( j > 0 )
{
second_corr[second_curr] = first[first_curr + 2];
second_corr[second_curr + 1] = first[first_curr + 2];
second_curr -= 2;
j--;
} /* while */
cvFree( &costTable );
cvFree( &matchEdges );
return CV_NO_ERR;
} /* icvDynamicCorrespond */
/*======================================================================================*/
static CvStatus
icvDynamicCorrespondMulti( int lines, /* number of scanlines */
int *first, /* s0|w0|s1|w1|...s(n-1)|w(n-1)|sn */
int *first_runs, /* numbers of runs */
int *second, int *second_runs, int *first_corr, /* s0'|e0'|s1'|e1'|... */
int *second_corr )
{
CvStatus error;
int currFirst;
int currSecond;
int currFirstCorr;
int currSecondCorr;
int n;
/* Test errors */
if( (lines < 1) ||
(first == 0) ||
(first_runs == 0) ||
(second == 0) || (second_runs == 0) || (first_corr == 0) || (second_corr == 0) )
return CV_BADFACTOR_ERR;
currFirst = 0;
currSecond = 0;
currFirstCorr = 0;
currSecondCorr = 0;
for( n = 0; n < lines; n++ )
{
error = icvDynamicCorrespond( &(first[currFirst]),
first_runs[n],
&(second[currSecond]),
second_runs[n],
&(first_corr[currFirstCorr]),
&(second_corr[currSecondCorr]) );
if( error != CV_NO_ERR )
return error;
currFirst += first_runs[n] * 2 + 1;
currSecond += second_runs[n] * 2 + 1;
currFirstCorr += first_runs[n] * 2;
currSecondCorr += second_runs[n] * 2;
}
return CV_NO_ERR;
} /* icvDynamicCorrespondMulti */
/*======================================================================================*/
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvDynamicCorrespondMulti
// Purpose: The functions
// Context:
// Parameters:
//
// Notes:
//F*/
CV_IMPL void
cvDynamicCorrespondMulti( int lines, /* number of scanlines */
int *first, /* s0|w0|s1|w1|...s(n-1)|w(n-1)|sn */
int *first_runs, /* numbers of runs */
int *second, int *second_runs, int *first_corr, /* s0'|e0'|s1'|e1'|... */
int *second_corr )
{
IPPI_CALL( icvDynamicCorrespondMulti( lines, /* number of scanlines */
first, /* s0|w0|s1|w1|...s(n-1)|w(n-1)|sn */
first_runs, /* numbers of runs */
second, second_runs, first_corr, /* s0'|e0'|s1'|e1'|... */
second_corr ));
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,138 @@
/*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"
#define CV_MAX2( a, b ) ((a)>(b) ? (a) : (b))
#define CV_MIN2( a, b ) ((a)<(b) ? (a) : (b))
/****************************************************************************************\
create hand mask
\****************************************************************************************/
static CvStatus icvCreateHandMask8uC1R(CvSeq * numbers,
uchar * image_mask, int step,
CvSize size, CvRect * roi )
{
CvSeqReader reader;
CvPoint pt;
int k_point;
int i_min, i_max, j_min, j_max;
if( numbers == NULL )
return CV_NULLPTR_ERR;
if( !CV_IS_SEQ_POINT_SET( numbers ))
return CV_BADFLAG_ERR;
i_max = j_max = 0;
i_min = size.height;
j_min = size.width;
cvStartReadSeq( numbers, &reader, 0 );
k_point = numbers->total;
assert( k_point > 0 );
if( k_point <= 0 )
return CV_BADSIZE_ERR;
memset( image_mask, 0, step * size.height );
while( k_point-- > 0 )
{
CV_READ_SEQ_ELEM( pt, reader );
i_min = CV_MIN2( i_min, pt.y );
i_max = CV_MAX2( i_max, pt.y );
j_min = CV_MIN2( j_min, pt.x );
j_max = CV_MAX2( j_max, pt.x );
*(image_mask + pt.y * step + pt.x) = 255;
}
roi->x = j_min;
roi->y = i_min;
roi->width = j_max - j_min + 1;
roi->height = i_max - i_min + 1;
return CV_OK;
}
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvCreateHandMask
// Purpose: creates hand mask image
// Context:
// Parameters:
// numbers - pointer to the input sequence of the point's indexes inside
// hand region
// img_mask - pointer to the result mask image
// roi - result hand mask ROI
//
// Notes:
//F*/
CV_IMPL void
cvCreateHandMask( CvSeq * numbers, IplImage * img_mask, CvRect * roi )
{
uchar *img_mask_data = 0;
int img_mask_step = 0;
CvSize img_mask_size;
CV_FUNCNAME( "cvCreateHandMask" );
__BEGIN__;
if( img_mask->depth != IPL_DEPTH_8U )
CV_ERROR( CV_BadDepth, cvUnsupportedFormat );
if( img_mask->nChannels != 1 )
CV_ERROR( CV_BadNumChannels, "output image have wrong number of channels" );
cvGetImageRawData( img_mask, &img_mask_data, &img_mask_step, &img_mask_size );
IPPI_CALL( icvCreateHandMask8uC1R( numbers, img_mask_data,
img_mask_step, img_mask_size, roi ));
__END__;
}

View File

@@ -0,0 +1,629 @@
/*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"
#if 0
#include <malloc.h>
//#include "decomppoly.h"
#define ZERO_CLOSE 0.00001f
#define ONE_CLOSE 0.99999f
#define CHECK_COLLINEARITY(vec1_x,vec1_y,vec2_x,vec2_y) \
if( vec1_x == 0 ) { \
if( vec1_y * vec2_y > 0 ) { \
return 0; \
} \
} \
else { \
if( vec1_x * vec2_x > 0 ) { \
return 0; \
} \
}
// determines if edge number one lies in counterclockwise
// earlier than edge number two
inline int icvIsFirstEdgeClosier( int x0,
int y0,
int x0_end,
int y0_end,
int x1_end,
int y1_end,
int x2_end,
int y2_end )
{
int mult, mult1, mult2;
int vec0_x, vec0_y;
int vec1_x, vec1_y;
int vec2_x, vec2_y;
vec0_x = x0_end - x0;
vec0_y = y0_end - y0;
vec1_x = x1_end - x0;
vec1_y = y1_end - y0;
vec2_x = x2_end - x0;
vec2_y = y2_end - y0;
mult1 = vec1_x * vec0_y - vec0_x * vec1_y;
mult2 = vec2_x * vec0_y - vec0_x * vec2_y;
if( mult1 == 0 ) {
CHECK_COLLINEARITY( vec0_x, vec0_y, vec1_x, vec1_y );
}
if( mult2 == 0 ) {
CHECK_COLLINEARITY( vec0_x, vec0_y, vec2_x, vec2_y );
}
if( mult1 > 0 && mult2 < 0 ) {
return 1;
}
if( mult1 < 0 && mult2 > 0 ) {
return -1;
}
mult = vec1_x * vec2_y - vec2_x * vec1_y;
if( mult == 0 ) {
CHECK_COLLINEARITY( vec1_x, vec1_y, vec2_x, vec2_y );
}
if( mult1 > 0 )
{
if( mult > 0 ) {
return -1;
}
else {
return 1;
}
} // if( mult1 > 0 )
else
{
if( mult1 != 0 ) {
if( mult > 0 ) {
return 1;
}
else {
return -1;
}
} // if( mult1 != 0 )
else {
if( mult2 > 0 ) {
return -1;
}
else {
return 1;
}
} // if( mult1 != 0 ) else
} // if( mult1 > 0 ) else
} // icvIsFirstEdgeClosier
bool icvEarCutTriangulation( CvPoint* contour,
int num,
int* outEdges,
int* numEdges )
{
int i;
int notFoundFlag = 0;
int begIndex = -1;
int isInternal;
int currentNum = num;
int index1, index2, index3;
int ix0, iy0, ix1, iy1, ix2, iy2;
int x1, y1, x2, y2, x3, y3;
int dx1, dy1, dx2, dy2;
int* pointExist = ( int* )0;
int det, det1, det2;
float t1, t2;
(*numEdges) = 0;
if( num <= 2 ) {
return false;
}
pointExist = ( int* )malloc( num * sizeof( int ) );
for( i = 0; i < num; i ++ ) {
pointExist[i] = 1;
}
for( i = 0; i < num; i ++ ) {
outEdges[ (*numEdges) * 2 ] = i;
if( i != num - 1 ) {
outEdges[ (*numEdges) * 2 + 1 ] = i + 1;
}
else {
outEdges[ (*numEdges) * 2 + 1 ] = 0;
}
(*numEdges) ++;
} // for( i = 0; i < num; i ++ )
// initializing data before while cycle
index1 = 0;
index2 = 1;
index3 = 2;
x1 = contour[ index1 ].x;
y1 = contour[ index1 ].y;
x2 = contour[ index2 ].x;
y2 = contour[ index2 ].y;
x3 = contour[ index3 ].x;
y3 = contour[ index3 ].y;
while( currentNum > 3 )
{
dx1 = x2 - x1;
dy1 = y2 - y1;
dx2 = x3 - x2;
dy2 = y3 - y2;
if( dx1 * dy2 - dx2 * dy1 < 0 ) // convex condition
{
// checking for noncrossing edge
ix1 = x3 - x1;
iy1 = y3 - y1;
isInternal = 1;
for( i = 0; i < num; i ++ )
{
if( i != num - 1 ) {
ix2 = contour[ i + 1 ].x - contour[ i ].x;
iy2 = contour[ i + 1 ].y - contour[ i ].y;
}
else {
ix2 = contour[ 0 ].x - contour[ i ].x;
iy2 = contour[ 0 ].y - contour[ i ].y;
}
ix0 = contour[ i ].x - x1;
iy0 = contour[ i ].y - y1;
det = ix2 * iy1 - ix1 * iy2;
det1 = ix2 * iy0 - ix0 * iy2;
if( det != 0.0f )
{
t1 = ( ( float )( det1 ) ) / det;
if( t1 > ZERO_CLOSE && t1 < ONE_CLOSE )
{
det2 = ix1 * iy0 - ix0 * iy1;
t2 = ( ( float )( det2 ) ) / det;
if( t2 > ZERO_CLOSE && t2 < ONE_CLOSE ) {
isInternal = 0;
}
} // if( t1 > ZERO_CLOSE && t1 < ONE_CLOSE )
} // if( det != 0.0f )
} // for( i = 0; i < (*numEdges); i ++ )
if( isInternal )
{
// this edge is internal
notFoundFlag = 0;
outEdges[ (*numEdges) * 2 ] = index1;
outEdges[ (*numEdges) * 2 + 1 ] = index3;
(*numEdges) ++;
pointExist[ index2 ] = 0;
index2 = index3;
x2 = x3;
y2 = y3;
currentNum --;
if( currentNum >= 3 ) {
do {
index3 ++;
if( index3 == num ) {
index3 = 0;
}
} while( !pointExist[ index3 ] );
x3 = contour[ index3 ].x;
y3 = contour[ index3 ].y;
} // if( currentNum >= 3 )
} // if( isInternal )
else {
// this edge intersects some other initial edges
if( !notFoundFlag ) {
notFoundFlag = 1;
begIndex = index1;
}
index1 = index2;
x1 = x2;
y1 = y2;
index2 = index3;
x2 = x3;
y2 = y3;
do {
index3 ++;
if( index3 == num ) {
index3 = 0;
}
if( index3 == begIndex ) {
if( pointExist ) {
free( pointExist );
}
return false;
}
} while( !pointExist[ index3 ] );
x3 = contour[ index3 ].x;
y3 = contour[ index3 ].y;
} // if( isInternal ) else
} // if( dx1 * dy2 - dx2 * dy1 < 0 )
else
{
if( !notFoundFlag ) {
notFoundFlag = 1;
begIndex = index1;
}
index1 = index2;
x1 = x2;
y1 = y2;
index2 = index3;
x2 = x3;
y2 = y3;
do {
index3 ++;
if( index3 == num ) {
index3 = 0;
}
if( index3 == begIndex ) {
if( pointExist ) {
free( pointExist );
}
return false;
}
} while( !pointExist[ index3 ] );
x3 = contour[ index3 ].x;
y3 = contour[ index3 ].y;
} // if( dx1 * dy2 - dx2 * dy1 < 0 ) else
} // while( currentNum > 3 )
if( pointExist ) {
free( pointExist );
}
return true;
} // icvEarCutTriangulation
inline bool icvFindTwoNeighbourEdges( CvPoint* contour,
int* edges,
int numEdges,
int vtxIdx,
int mainEdgeIdx,
int* leftEdgeIdx,
int* rightEdgeIdx )
{
int i;
int compRes;
int vec0_x, vec0_y;
int x0, y0, x0_end, y0_end;
int x1_left = 0, y1_left = 0, x1_right = 0, y1_right = 0, x2, y2;
(*leftEdgeIdx) = -1;
(*rightEdgeIdx) = -1;
if( edges[ mainEdgeIdx * 2 ] == vtxIdx ) {
x0 = contour[ vtxIdx ].x;
y0 = contour[ vtxIdx ].y;
x0_end = contour[ edges[ mainEdgeIdx * 2 + 1 ] ].x;
y0_end = contour[ edges[ mainEdgeIdx * 2 + 1 ] ].y;
vec0_x = x0_end - x0;
vec0_y = y0_end - y0;
}
else {
//x0 = contour[ edges[ mainEdgeIdx * 2 ] ].x;
//y0 = contour[ edges[ mainEdgeIdx * 2 ] ].y;
//x0_end = contour[ vtxIdx ].x;
//y0_end = contour[ vtxIdx ].y;
x0 = contour[ vtxIdx ].x;
y0 = contour[ vtxIdx ].y;
x0_end = contour[ edges[ mainEdgeIdx * 2 ] ].x;
y0_end = contour[ edges[ mainEdgeIdx * 2 ] ].y;
vec0_x = x0_end - x0;
vec0_y = y0_end - y0;
}
for( i = 0; i < numEdges; i ++ )
{
if( ( i != mainEdgeIdx ) &&
( edges[ i * 2 ] == vtxIdx || edges[ i * 2 + 1 ] == vtxIdx ) )
{
if( (*leftEdgeIdx) == -1 )
{
(*leftEdgeIdx) = (*rightEdgeIdx) = i;
if( edges[ i * 2 ] == vtxIdx ) {
x1_left = x1_right = contour[ edges[ i * 2 + 1 ] ].x;
y1_left = y1_right = contour[ edges[ i * 2 + 1 ] ].y;
}
else {
x1_left = x1_right = contour[ edges[ i * 2 ] ].x;
y1_left = y1_right = contour[ edges[ i * 2 ] ].y;
}
} // if( (*leftEdgeIdx) == -1 )
else
{
if( edges[ i * 2 ] == vtxIdx ) {
x2 = contour[ edges[ i * 2 + 1 ] ].x;
y2 = contour[ edges[ i * 2 + 1 ] ].y;
}
else {
x2 = contour[ edges[ i * 2 ] ].x;
y2 = contour[ edges[ i * 2 ] ].y;
}
compRes = icvIsFirstEdgeClosier( x0,
y0, x0_end, y0_end, x1_left, y1_left, x2, y2 );
if( compRes == 0 ) {
return false;
}
if( compRes == -1 ) {
(*leftEdgeIdx) = i;
x1_left = x2;
y1_left = y2;
} // if( compRes == -1 )
else {
compRes = icvIsFirstEdgeClosier( x0,
y0, x0_end, y0_end, x1_right, y1_right, x2, y2 );
if( compRes == 0 ) {
return false;
}
if( compRes == 1 ) {
(*rightEdgeIdx) = i;
x1_right = x2;
y1_right = y2;
}
} // if( compRes == -1 ) else
} // if( (*leftEdgeIdx) == -1 ) else
} // if( ( i != mainEdgesIdx ) && ...
} // for( i = 0; i < numEdges; i ++ )
return true;
} // icvFindTwoNeighbourEdges
bool icvFindReferences( CvPoint* contour,
int num,
int* outEdges,
int* refer,
int* numEdges )
{
int i;
int currPntIdx;
int leftEdgeIdx, rightEdgeIdx;
if( icvEarCutTriangulation( contour, num, outEdges, numEdges ) )
{
for( i = 0; i < (*numEdges); i ++ )
{
refer[ i * 4 ] = -1;
refer[ i * 4 + 1 ] = -1;
refer[ i * 4 + 2 ] = -1;
refer[ i * 4 + 3 ] = -1;
} // for( i = 0; i < (*numEdges); i ++ )
for( i = 0; i < (*numEdges); i ++ )
{
currPntIdx = outEdges[ i * 2 ];
if( !icvFindTwoNeighbourEdges( contour,
outEdges, (*numEdges), currPntIdx,
i, &leftEdgeIdx, &rightEdgeIdx ) )
{
return false;
} // if( !icvFindTwoNeighbourEdges( contour, ...
else
{
if( outEdges[ leftEdgeIdx * 2 ] == currPntIdx ) {
if( refer[ i * 4 ] == -1 ) {
refer[ i * 4 ] = ( leftEdgeIdx << 2 );
}
}
else {
if( refer[ i * 4 ] == -1 ) {
refer[ i * 4 ] = ( leftEdgeIdx << 2 ) | 2;
}
}
if( outEdges[ rightEdgeIdx * 2 ] == currPntIdx ) {
if( refer[ i * 4 + 1 ] == -1 ) {
refer[ i * 4 + 1 ] = ( rightEdgeIdx << 2 ) | 3;
}
}
else {
if( refer[ i * 4 + 1 ] == -1 ) {
refer[ i * 4 + 1 ] = ( rightEdgeIdx << 2 ) | 1;
}
}
} // if( !icvFindTwoNeighbourEdges( contour, ... ) else
currPntIdx = outEdges[ i * 2 + 1 ];
if( i == 18 ) {
i = i;
}
if( !icvFindTwoNeighbourEdges( contour,
outEdges, (*numEdges), currPntIdx,
i, &leftEdgeIdx, &rightEdgeIdx ) )
{
return false;
} // if( !icvFindTwoNeighbourEdges( contour, ...
else
{
if( outEdges[ leftEdgeIdx * 2 ] == currPntIdx ) {
if( refer[ i * 4 + 3 ] == -1 ) {
refer[ i * 4 + 3 ] = ( leftEdgeIdx << 2 );
}
}
else {
if( refer[ i * 4 + 3 ] == -1 ) {
refer[ i * 4 + 3 ] = ( leftEdgeIdx << 2 ) | 2;
}
}
if( outEdges[ rightEdgeIdx * 2 ] == currPntIdx ) {
if( refer[ i * 4 + 2 ] == -1 ) {
refer[ i * 4 + 2 ] = ( rightEdgeIdx << 2 ) | 3;
}
}
else {
if( refer[ i * 4 + 2 ] == -1 ) {
refer[ i * 4 + 2 ] = ( rightEdgeIdx << 2 ) | 1;
}
}
} // if( !icvFindTwoNeighbourEdges( contour, ... ) else
} // for( i = 0; i < (*numEdges); i ++ )
} // if( icvEarCutTriangulation( contour, num, outEdges, numEdges ) )
else {
return false;
} // if( icvEarCutTriangulation( contour, num, outEdges, ... ) else
return true;
} // icvFindReferences
void cvDecompPoly( CvContour* cont,
CvSubdiv2D** subdiv,
CvMemStorage* storage )
{
int* memory;
CvPoint* contour;
int* outEdges;
int* refer;
CvSubdiv2DPoint** pntsPtrs;
CvQuadEdge2D** edgesPtrs;
int numVtx;
int numEdges;
int i;
CvSeqReader reader;
CvPoint2D32f pnt;
CvQuadEdge2D* quadEdge;
numVtx = cont -> total;
if( numVtx < 3 ) {
return;
}
*subdiv = ( CvSubdiv2D* )0;
memory = ( int* )malloc( sizeof( int ) * ( numVtx * 2
+ numVtx * numVtx * 2 * 5 )
+ sizeof( CvQuadEdge2D* ) * ( numVtx * numVtx )
+ sizeof( CvSubdiv2DPoint* ) * ( numVtx * 2 ) );
contour = ( CvPoint* )memory;
outEdges = ( int* )( contour + numVtx );
refer = outEdges + numVtx * numVtx * 2;
edgesPtrs = ( CvQuadEdge2D** )( refer + numVtx * numVtx * 4 );
pntsPtrs = ( CvSubdiv2DPoint** )( edgesPtrs + numVtx * numVtx );
cvStartReadSeq( ( CvSeq* )cont, &reader, 0 );
for( i = 0; i < numVtx; i ++ )
{
CV_READ_SEQ_ELEM( (contour[ i ]), reader );
} // for( i = 0; i < numVtx; i ++ )
if( !icvFindReferences( contour, numVtx, outEdges, refer, &numEdges ) )
{
free( memory );
return;
} // if( !icvFindReferences( contour, numVtx, outEdges, refer, ...
*subdiv = cvCreateSubdiv2D( CV_SEQ_KIND_SUBDIV2D,
sizeof( CvSubdiv2D ),
sizeof( CvSubdiv2DPoint ),
sizeof( CvQuadEdge2D ),
storage );
for( i = 0; i < numVtx; i ++ )
{
pnt.x = ( float )contour[ i ].x;
pnt.y = ( float )contour[ i ].y;
pntsPtrs[ i ] = cvSubdiv2DAddPoint( *subdiv, pnt, 0 );
} // for( i = 0; i < numVtx; i ++ )
for( i = 0; i < numEdges; i ++ )
{
edgesPtrs[ i ] = ( CvQuadEdge2D* )
( cvSubdiv2DMakeEdge( *subdiv ) & 0xfffffffc );
} // for( i = 0; i < numEdges; i ++ )
for( i = 0; i < numEdges; i ++ )
{
quadEdge = edgesPtrs[ i ];
quadEdge -> next[ 0 ] =
( ( CvSubdiv2DEdge )edgesPtrs[ refer[ i * 4 ] >> 2 ] )
| ( refer[ i * 4 ] & 3 );
quadEdge -> next[ 1 ] =
( ( CvSubdiv2DEdge )edgesPtrs[ refer[ i * 4 + 1 ] >> 2 ] )
| ( refer[ i * 4 + 1 ] & 3 );
quadEdge -> next[ 2 ] =
( ( CvSubdiv2DEdge )edgesPtrs[ refer[ i * 4 + 2 ] >> 2 ] )
| ( refer[ i * 4 + 2 ] & 3 );
quadEdge -> next[ 3 ] =
( ( CvSubdiv2DEdge )edgesPtrs[ refer[ i * 4 + 3 ] >> 2 ] )
| ( refer[ i * 4 + 3 ] & 3 );
quadEdge -> pt[ 0 ] = pntsPtrs[ outEdges[ i * 2 ] ];
quadEdge -> pt[ 1 ] = ( CvSubdiv2DPoint* )0;
quadEdge -> pt[ 2 ] = pntsPtrs[ outEdges[ i * 2 + 1 ] ];
quadEdge -> pt[ 3 ] = ( CvSubdiv2DPoint* )0;
} // for( i = 0; i < numEdges; i ++ )
(*subdiv) -> topleft.x = ( float )cont -> rect.x;
(*subdiv) -> topleft.y = ( float )cont -> rect.y;
(*subdiv) -> bottomright.x =
( float )( cont -> rect.x + cont -> rect.width );
(*subdiv) -> bottomright.y =
( float )( cont -> rect.y + cont -> rect.height );
free( memory );
return;
} // cvDecompPoly
#endif
// End of file decomppoly.cpp

View File

@@ -0,0 +1,402 @@
/*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"
typedef struct _PointInfo
{
CvPoint pt;
int left_neigh;
int right_neigh;
}
icvPointInfo;
static CvStatus
icvFindDominantPointsIPAN( CvSeq * contour,
CvMemStorage * storage,
CvSeq ** corners, int dmin2, int dmax2, int dneigh2, float amax )
{
CvStatus status = CV_OK;
/* variables */
int n = contour->total;
float *sharpness;
float *distance;
icvPointInfo *ptInf;
int i, j, k;
CvSeqWriter writer;
float mincos = (float) cos( 3.14159265359 * amax / 180 );
/* check bad arguments */
if( contour == NULL )
return CV_NULLPTR_ERR;
if( storage == NULL )
return CV_NULLPTR_ERR;
if( corners == NULL )
return CV_NULLPTR_ERR;
if( dmin2 < 0 )
return CV_BADSIZE_ERR;
if( dmax2 < dmin2 )
return CV_BADSIZE_ERR;
if( (dneigh2 > dmax2) || (dneigh2 < 0) )
return CV_BADSIZE_ERR;
if( (amax < 0) || (amax > 180) )
return CV_BADSIZE_ERR;
sharpness = (float *) cvAlloc( n * sizeof( float ));
distance = (float *) cvAlloc( n * sizeof( float ));
ptInf = (icvPointInfo *) cvAlloc( n * sizeof( icvPointInfo ));
/*****************************************************************************************/
/* First pass */
/*****************************************************************************************/
if( CV_IS_SEQ_CHAIN_CONTOUR( contour ))
{
CvChainPtReader reader;
cvStartReadChainPoints( (CvChain *) contour, &reader );
for( i = 0; i < n; i++ )
{
CV_READ_CHAIN_POINT( ptInf[i].pt, reader );
}
}
else if( CV_IS_SEQ_POINT_SET( contour ))
{
CvSeqReader reader;
cvStartReadSeq( contour, &reader, 0 );
for( i = 0; i < n; i++ )
{
CV_READ_SEQ_ELEM( ptInf[i].pt, reader );
}
}
else
{
return CV_BADFLAG_ERR;
}
for( i = 0; i < n; i++ )
{
/* find nearest suitable points
which satisfy distance constraint >dmin */
int left_near = 0;
int right_near = 0;
int left_far, right_far;
float dist_l = 0;
float dist_r = 0;
int i_plus = 0;
int i_minus = 0;
float max_cos_alpha;
/* find right minimum */
while( dist_r < dmin2 )
{
float dx, dy;
int ind;
if( i_plus >= n )
goto error;
right_near = i_plus;
if( dist_r < dneigh2 )
ptInf[i].right_neigh = i_plus;
i_plus++;
ind = (i + i_plus) % n;
dx = (float) (ptInf[i].pt.x - ptInf[ind].pt.x);
dy = (float) (ptInf[i].pt.y - ptInf[ind].pt.y);
dist_r = dx * dx + dy * dy;
}
/* find right maximum */
while( dist_r <= dmax2 )
{
float dx, dy;
int ind;
if( i_plus >= n )
goto error;
distance[(i + i_plus) % n] = cvSqrt( dist_r );
if( dist_r < dneigh2 )
ptInf[i].right_neigh = i_plus;
i_plus++;
right_far = i_plus;
ind = (i + i_plus) % n;
dx = (float) (ptInf[i].pt.x - ptInf[ind].pt.x);
dy = (float) (ptInf[i].pt.y - ptInf[ind].pt.y);
dist_r = dx * dx + dy * dy;
}
right_far = i_plus;
/* left minimum */
while( dist_l < dmin2 )
{
float dx, dy;
int ind;
if( i_minus <= -n )
goto error;
left_near = i_minus;
if( dist_l < dneigh2 )
ptInf[i].left_neigh = i_minus;
i_minus--;
ind = i + i_minus;
ind = (ind < 0) ? (n + ind) : ind;
dx = (float) (ptInf[i].pt.x - ptInf[ind].pt.x);
dy = (float) (ptInf[i].pt.y - ptInf[ind].pt.y);
dist_l = dx * dx + dy * dy;
}
/* find left maximum */
while( dist_l <= dmax2 )
{
float dx, dy;
int ind;
if( i_minus <= -n )
goto error;
ind = i + i_minus;
ind = (ind < 0) ? (n + ind) : ind;
distance[ind] = cvSqrt( dist_l );
if( dist_l < dneigh2 )
ptInf[i].left_neigh = i_minus;
i_minus--;
left_far = i_minus;
ind = i + i_minus;
ind = (ind < 0) ? (n + ind) : ind;
dx = (float) (ptInf[i].pt.x - ptInf[ind].pt.x);
dy = (float) (ptInf[i].pt.y - ptInf[ind].pt.y);
dist_l = dx * dx + dy * dy;
}
left_far = i_minus;
if( (i_plus - i_minus) > n + 2 )
goto error;
max_cos_alpha = -1;
for( j = left_far + 1; j < left_near; j++ )
{
float dx, dy;
float a, a2;
int leftind = i + j;
leftind = (leftind < 0) ? (n + leftind) : leftind;
a = distance[leftind];
a2 = a * a;
for( k = right_near + 1; k < right_far; k++ )
{
int ind = (i + k) % n;
float c2, cosalpha;
float b = distance[ind];
float b2 = b * b;
/* compute cosinus */
dx = (float) (ptInf[leftind].pt.x - ptInf[ind].pt.x);
dy = (float) (ptInf[leftind].pt.y - ptInf[ind].pt.y);
c2 = dx * dx + dy * dy;
cosalpha = (a2 + b2 - c2) / (2 * a * b);
max_cos_alpha = MAX( max_cos_alpha, cosalpha );
if( max_cos_alpha < mincos )
max_cos_alpha = -1;
sharpness[i] = max_cos_alpha;
}
}
}
/*****************************************************************************************/
/* Second pass */
/*****************************************************************************************/
cvStartWriteSeq( (contour->flags & ~CV_SEQ_ELTYPE_MASK) | CV_SEQ_ELTYPE_INDEX,
sizeof( CvSeq ), sizeof( int ), storage, &writer );
/* second pass - nonmaxima suppression */
/* neighborhood of point < dneigh2 */
for( i = 0; i < n; i++ )
{
int suppressed = 0;
if( sharpness[i] == -1 )
continue;
for( j = 1; (j <= ptInf[i].right_neigh) && (suppressed == 0); j++ )
{
if( sharpness[i] < sharpness[(i + j) % n] )
suppressed = 1;
}
for( j = -1; (j >= ptInf[i].left_neigh) && (suppressed == 0); j-- )
{
int ind = i + j;
ind = (ind < 0) ? (n + ind) : ind;
if( sharpness[i] < sharpness[ind] )
suppressed = 1;
}
if( !suppressed )
CV_WRITE_SEQ_ELEM( i, writer );
}
*corners = cvEndWriteSeq( &writer );
cvFree( &sharpness );
cvFree( &distance );
cvFree( &ptInf );
return status;
error:
/* dmax is so big (more than contour diameter)
that algorithm could become infinite cycle */
cvFree( &sharpness );
cvFree( &distance );
cvFree( &ptInf );
return CV_BADRANGE_ERR;
}
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: icvFindDominantPoints
// Purpose:
// Applies some algorithm to find dominant points ( corners ) of contour
//
// Context:
// Parameters:
// contours - pointer to input contour object.
// out_numbers - array of dominant points indices
// count - length of out_numbers array on input
// and numbers of founded dominant points on output
//
// method - only CV_DOMINANT_IPAN now
// parameters - array of parameters
// for IPAN algorithm
// [0] - minimal distance
// [1] - maximal distance
// [2] - neighborhood distance (must be not greater than dmaximal distance)
// [3] - maximal possible angle of curvature
// Returns:
// CV_OK or error code
// Notes:
// User must allocate out_numbers array. If it is small - function fills array
// with part of points and returns error
//F*/
CV_IMPL CvSeq*
cvFindDominantPoints( CvSeq * contour, CvMemStorage * storage, int method,
double parameter1, double parameter2, double parameter3, double parameter4 )
{
CvSeq* corners = 0;
if( !contour )
CV_Error( CV_StsNullPtr, "" );
if( !storage )
storage = contour->storage;
if( !storage )
CV_Error( CV_StsNullPtr, "" );
switch (method)
{
case CV_DOMINANT_IPAN:
{
int dmin = cvRound(parameter1);
int dmax = cvRound(parameter2);
int dneigh = cvRound(parameter3);
int amax = cvRound(parameter4);
if( amax == 0 )
amax = 150;
if( dmin == 0 )
dmin = 7;
if( dmax == 0 )
dmax = dmin + 2;
if( dneigh == 0 )
dneigh = dmin;
IPPI_CALL( icvFindDominantPointsIPAN( contour, storage, &corners,
dmin*dmin, dmax*dmax, dneigh*dneigh, (float)amax ));
}
break;
default:
CV_Error( CV_StsBadArg, "" );
}
return corners;
}
/* End of file. */

View File

@@ -0,0 +1,554 @@
/*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"
/****************************************************************************************\
The code below is some modification of Stan Birchfield's algorithm described in:
Depth Discontinuities by Pixel-to-Pixel Stereo
Stan Birchfield and Carlo Tomasi
International Journal of Computer Vision,
35(3): 269-293, December 1999.
This implementation uses different cost function that results in
O(pixPerRow*maxDisparity) complexity of dynamic programming stage versus
O(pixPerRow*log(pixPerRow)*maxDisparity) in the above paper.
\****************************************************************************************/
/****************************************************************************************\
* Find stereo correspondence by dynamic programming algorithm *
\****************************************************************************************/
#define ICV_DP_STEP_LEFT 0
#define ICV_DP_STEP_UP 1
#define ICV_DP_STEP_DIAG 2
#define ICV_BIRCH_DIFF_LUM 5
#define ICV_MAX_DP_SUM_VAL (INT_MAX/4)
typedef struct _CvDPCell
{
uchar step; //local-optimal step
int sum; //current sum
}_CvDPCell;
typedef struct _CvRightImData
{
uchar min_val, max_val;
} _CvRightImData;
#define CV_IMAX3(a,b,c) ((temp3 = (a) >= (b) ? (a) : (b)),(temp3 >= (c) ? temp3 : (c)))
#define CV_IMIN3(a,b,c) ((temp3 = (a) <= (b) ? (a) : (b)),(temp3 <= (c) ? temp3 : (c)))
void icvFindStereoCorrespondenceByBirchfieldDP( uchar* src1, uchar* src2,
uchar* disparities,
CvSize size, int widthStep,
int maxDisparity,
float _param1, float _param2,
float _param3, float _param4,
float _param5 )
{
int x, y, i, j, temp3;
int d, s;
int dispH = maxDisparity + 3;
uchar *dispdata;
int imgW = size.width;
int imgH = size.height;
uchar val, prevval, prev, curr;
int min_val;
uchar* dest = disparities;
int param1 = cvRound(_param1);
int param2 = cvRound(_param2);
int param3 = cvRound(_param3);
int param4 = cvRound(_param4);
int param5 = cvRound(_param5);
#define CELL(d,x) cells[(d)+(x)*dispH]
uchar* dsi = (uchar*)cvAlloc(sizeof(uchar)*imgW*dispH);
uchar* edges = (uchar*)cvAlloc(sizeof(uchar)*imgW*imgH);
_CvDPCell* cells = (_CvDPCell*)cvAlloc(sizeof(_CvDPCell)*imgW*MAX(dispH,(imgH+1)/2));
_CvRightImData* rData = (_CvRightImData*)cvAlloc(sizeof(_CvRightImData)*imgW);
int* reliabilities = (int*)cells;
for( y = 0; y < imgH; y++ )
{
uchar* srcdata1 = src1 + widthStep * y;
uchar* srcdata2 = src2 + widthStep * y;
//init rData
prevval = prev = srcdata2[0];
for( j = 1; j < imgW; j++ )
{
curr = srcdata2[j];
val = (uchar)((curr + prev)>>1);
rData[j-1].max_val = (uchar)CV_IMAX3( val, prevval, prev );
rData[j-1].min_val = (uchar)CV_IMIN3( val, prevval, prev );
prevval = val;
prev = curr;
}
rData[j-1] = rData[j-2];//last elem
// fill dissimularity space image
for( i = 1; i <= maxDisparity + 1; i++ )
{
dsi += imgW;
rData--;
for( j = i - 1; j < imgW - 1; j++ )
{
int t;
if( (t = srcdata1[j] - rData[j+1].max_val) >= 0 )
{
dsi[j] = (uchar)t;
}
else if( (t = rData[j+1].min_val - srcdata1[j]) >= 0 )
{
dsi[j] = (uchar)t;
}
else
{
dsi[j] = 0;
}
}
}
dsi -= (maxDisparity+1)*imgW;
rData += maxDisparity+1;
//intensity gradients image construction
//left row
edges[y*imgW] = edges[y*imgW+1] = edges[y*imgW+2] = 2;
edges[y*imgW+imgW-1] = edges[y*imgW+imgW-2] = edges[y*imgW+imgW-3] = 1;
for( j = 3; j < imgW-4; j++ )
{
edges[y*imgW+j] = 0;
if( ( CV_IMAX3( srcdata1[j-3], srcdata1[j-2], srcdata1[j-1] ) -
CV_IMIN3( srcdata1[j-3], srcdata1[j-2], srcdata1[j-1] ) ) >= ICV_BIRCH_DIFF_LUM )
{
edges[y*imgW+j] |= 1;
}
if( ( CV_IMAX3( srcdata2[j+3], srcdata2[j+2], srcdata2[j+1] ) -
CV_IMIN3( srcdata2[j+3], srcdata2[j+2], srcdata2[j+1] ) ) >= ICV_BIRCH_DIFF_LUM )
{
edges[y*imgW+j] |= 2;
}
}
//find correspondence using dynamical programming
//init DP table
for( x = 0; x < imgW; x++ )
{
CELL(0,x).sum = CELL(dispH-1,x).sum = ICV_MAX_DP_SUM_VAL;
CELL(0,x).step = CELL(dispH-1,x).step = ICV_DP_STEP_LEFT;
}
for( d = 2; d < dispH; d++ )
{
CELL(d,d-2).sum = ICV_MAX_DP_SUM_VAL;
CELL(d,d-2).step = ICV_DP_STEP_UP;
}
CELL(1,0).sum = 0;
CELL(1,0).step = ICV_DP_STEP_LEFT;
for( x = 1; x < imgW; x++ )
{
int d = MIN( x + 1, maxDisparity + 1);
uchar* _edges = edges + y*imgW + x;
int e0 = _edges[0] & 1;
_CvDPCell* _cell = cells + x*dispH;
do
{
int s = dsi[d*imgW+x];
int sum[3];
//check left step
sum[0] = _cell[d-dispH].sum - param2;
//check up step
if( _cell[d+1].step != ICV_DP_STEP_DIAG && e0 )
{
sum[1] = _cell[d+1].sum + param1;
if( _cell[d-1-dispH].step != ICV_DP_STEP_UP && (_edges[1-d] & 2) )
{
int t;
sum[2] = _cell[d-1-dispH].sum + param1;
t = sum[1] < sum[0];
//choose local-optimal pass
if( sum[t] <= sum[2] )
{
_cell[d].step = (uchar)t;
_cell[d].sum = sum[t] + s;
}
else
{
_cell[d].step = ICV_DP_STEP_DIAG;
_cell[d].sum = sum[2] + s;
}
}
else
{
if( sum[0] <= sum[1] )
{
_cell[d].step = ICV_DP_STEP_LEFT;
_cell[d].sum = sum[0] + s;
}
else
{
_cell[d].step = ICV_DP_STEP_UP;
_cell[d].sum = sum[1] + s;
}
}
}
else if( _cell[d-1-dispH].step != ICV_DP_STEP_UP && (_edges[1-d] & 2) )
{
sum[2] = _cell[d-1-dispH].sum + param1;
if( sum[0] <= sum[2] )
{
_cell[d].step = ICV_DP_STEP_LEFT;
_cell[d].sum = sum[0] + s;
}
else
{
_cell[d].step = ICV_DP_STEP_DIAG;
_cell[d].sum = sum[2] + s;
}
}
else
{
_cell[d].step = ICV_DP_STEP_LEFT;
_cell[d].sum = sum[0] + s;
}
}
while( --d );
}// for x
//extract optimal way and fill disparity image
dispdata = dest + widthStep * y;
//find min_val
min_val = ICV_MAX_DP_SUM_VAL;
for( i = 1; i <= maxDisparity + 1; i++ )
{
if( min_val > CELL(i,imgW-1).sum )
{
d = i;
min_val = CELL(i,imgW-1).sum;
}
}
//track optimal pass
for( x = imgW - 1; x > 0; x-- )
{
dispdata[x] = (uchar)(d - 1);
while( CELL(d,x).step == ICV_DP_STEP_UP ) d++;
if ( CELL(d,x).step == ICV_DP_STEP_DIAG )
{
s = x;
while( CELL(d,x).step == ICV_DP_STEP_DIAG )
{
d--;
x--;
}
for( i = x; i < s; i++ )
{
dispdata[i] = (uchar)(d-1);
}
}
}//for x
}// for y
//Postprocessing the Disparity Map
//remove obvious errors in the disparity map
for( x = 0; x < imgW; x++ )
{
for( y = 1; y < imgH - 1; y++ )
{
if( dest[(y-1)*widthStep+x] == dest[(y+1)*widthStep+x] )
{
dest[y*widthStep+x] = dest[(y-1)*widthStep+x];
}
}
}
//compute intensity Y-gradients
for( x = 0; x < imgW; x++ )
{
for( y = 1; y < imgH - 1; y++ )
{
if( ( CV_IMAX3( src1[(y-1)*widthStep+x], src1[y*widthStep+x],
src1[(y+1)*widthStep+x] ) -
CV_IMIN3( src1[(y-1)*widthStep+x], src1[y*widthStep+x],
src1[(y+1)*widthStep+x] ) ) >= ICV_BIRCH_DIFF_LUM )
{
edges[y*imgW+x] |= 4;
edges[(y+1)*imgW+x] |= 4;
edges[(y-1)*imgW+x] |= 4;
y++;
}
}
}
//remove along any particular row, every gradient
//for which two adjacent columns do not agree.
for( y = 0; y < imgH; y++ )
{
prev = edges[y*imgW];
for( x = 1; x < imgW - 1; x++ )
{
curr = edges[y*imgW+x];
if( (curr & 4) &&
( !( prev & 4 ) ||
!( edges[y*imgW+x+1] & 4 ) ) )
{
edges[y*imgW+x] -= 4;
}
prev = curr;
}
}
// define reliability
for( x = 0; x < imgW; x++ )
{
for( y = 1; y < imgH; y++ )
{
i = y - 1;
for( ; y < imgH && dest[y*widthStep+x] == dest[(y-1)*widthStep+x]; y++ )
;
s = y - i;
for( ; i < y; i++ )
{
reliabilities[i*imgW+x] = s;
}
}
}
//Y - propagate reliable regions
for( x = 0; x < imgW; x++ )
{
for( y = 0; y < imgH; y++ )
{
d = dest[y*widthStep+x];
if( reliabilities[y*imgW+x] >= param4 && !(edges[y*imgW+x] & 4) &&
d > 0 )//highly || moderately
{
disparities[y*widthStep+x] = (uchar)d;
//up propagation
for( i = y - 1; i >= 0; i-- )
{
if( ( edges[i*imgW+x] & 4 ) ||
( dest[i*widthStep+x] < d &&
reliabilities[i*imgW+x] >= param3 ) ||
( reliabilities[y*imgW+x] < param5 &&
dest[i*widthStep+x] - 1 == d ) ) break;
disparities[i*widthStep+x] = (uchar)d;
}
//down propagation
for( i = y + 1; i < imgH; i++ )
{
if( ( edges[i*imgW+x] & 4 ) ||
( dest[i*widthStep+x] < d &&
reliabilities[i*imgW+x] >= param3 ) ||
( reliabilities[y*imgW+x] < param5 &&
dest[i*widthStep+x] - 1 == d ) ) break;
disparities[i*widthStep+x] = (uchar)d;
}
y = i - 1;
}
else
{
disparities[y*widthStep+x] = (uchar)d;
}
}
}
// define reliability along X
for( y = 0; y < imgH; y++ )
{
for( x = 1; x < imgW; x++ )
{
i = x - 1;
for( ; x < imgW && dest[y*widthStep+x] == dest[y*widthStep+x-1]; x++ );
s = x - i;
for( ; i < x; i++ )
{
reliabilities[y*imgW+i] = s;
}
}
}
//X - propagate reliable regions
for( y = 0; y < imgH; y++ )
{
for( x = 0; x < imgW; x++ )
{
d = dest[y*widthStep+x];
if( reliabilities[y*imgW+x] >= param4 && !(edges[y*imgW+x] & 1) &&
d > 0 )//highly || moderately
{
disparities[y*widthStep+x] = (uchar)d;
//up propagation
for( i = x - 1; i >= 0; i-- )
{
if( (edges[y*imgW+i] & 1) ||
( dest[y*widthStep+i] < d &&
reliabilities[y*imgW+i] >= param3 ) ||
( reliabilities[y*imgW+x] < param5 &&
dest[y*widthStep+i] - 1 == d ) ) break;
disparities[y*widthStep+i] = (uchar)d;
}
//down propagation
for( i = x + 1; i < imgW; i++ )
{
if( (edges[y*imgW+i] & 1) ||
( dest[y*widthStep+i] < d &&
reliabilities[y*imgW+i] >= param3 ) ||
( reliabilities[y*imgW+x] < param5 &&
dest[y*widthStep+i] - 1 == d ) ) break;
disparities[y*widthStep+i] = (uchar)d;
}
x = i - 1;
}
else
{
disparities[y*widthStep+x] = (uchar)d;
}
}
}
//release resources
cvFree( &dsi );
cvFree( &edges );
cvFree( &cells );
cvFree( &rData );
}
/*F///////////////////////////////////////////////////////////////////////////
//
// Name: cvFindStereoCorrespondence
// Purpose: find stereo correspondence on stereo-pair
// Context:
// Parameters:
// leftImage - left image of stereo-pair (format 8uC1).
// rightImage - right image of stereo-pair (format 8uC1).
// mode -mode of correspondance retrieval (now CV_RETR_DP_BIRCHFIELD only)
// dispImage - destination disparity image
// maxDisparity - maximal disparity
// param1, param2, param3, param4, param5 - parameters of algorithm
// Returns:
// Notes:
// Images must be rectified.
// All images must have format 8uC1.
//F*/
CV_IMPL void
cvFindStereoCorrespondence(
const CvArr* leftImage, const CvArr* rightImage,
int mode,
CvArr* depthImage,
int maxDisparity,
double param1, double param2, double param3,
double param4, double param5 )
{
CV_FUNCNAME( "cvFindStereoCorrespondence" );
__BEGIN__;
CvMat *src1, *src2;
CvMat *dst;
CvMat src1_stub, src2_stub, dst_stub;
int coi;
CV_CALL( src1 = cvGetMat( leftImage, &src1_stub, &coi ));
if( coi ) CV_ERROR( CV_BadCOI, "COI is not supported by the function" );
CV_CALL( src2 = cvGetMat( rightImage, &src2_stub, &coi ));
if( coi ) CV_ERROR( CV_BadCOI, "COI is not supported by the function" );
CV_CALL( dst = cvGetMat( depthImage, &dst_stub, &coi ));
if( coi ) CV_ERROR( CV_BadCOI, "COI is not supported by the function" );
// check args
if( CV_MAT_TYPE( src1->type ) != CV_8UC1 ||
CV_MAT_TYPE( src2->type ) != CV_8UC1 ||
CV_MAT_TYPE( dst->type ) != CV_8UC1) CV_ERROR(CV_StsUnsupportedFormat,
"All images must be single-channel and have 8u" );
if( !CV_ARE_SIZES_EQ( src1, src2 ) || !CV_ARE_SIZES_EQ( src1, dst ) )
CV_ERROR( CV_StsUnmatchedSizes, "" );
if( maxDisparity <= 0 || maxDisparity >= src1->width || maxDisparity > 255 )
CV_ERROR(CV_StsOutOfRange,
"parameter /maxDisparity/ is out of range");
if( mode == CV_DISPARITY_BIRCHFIELD )
{
if( param1 == CV_UNDEF_SC_PARAM ) param1 = CV_IDP_BIRCHFIELD_PARAM1;
if( param2 == CV_UNDEF_SC_PARAM ) param2 = CV_IDP_BIRCHFIELD_PARAM2;
if( param3 == CV_UNDEF_SC_PARAM ) param3 = CV_IDP_BIRCHFIELD_PARAM3;
if( param4 == CV_UNDEF_SC_PARAM ) param4 = CV_IDP_BIRCHFIELD_PARAM4;
if( param5 == CV_UNDEF_SC_PARAM ) param5 = CV_IDP_BIRCHFIELD_PARAM5;
CV_CALL( icvFindStereoCorrespondenceByBirchfieldDP( src1->data.ptr,
src2->data.ptr, dst->data.ptr,
cvGetMatSize( src1 ), src1->step,
maxDisparity, (float)param1, (float)param2, (float)param3,
(float)param4, (float)param5 ) );
}
else
{
CV_ERROR( CV_StsBadArg, "Unsupported mode of function" );
}
__END__;
}
/* End of file. */

File diff suppressed because it is too large Load Diff

1381
modules/legacy/src/enmin.cpp Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,268 @@
/*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"
#ifdef WIN32 /* make sure it builds under Linux whenever it is included into Makefile.am or not. */
//void icvCutContour( CvSeq* current, IplImage* image );
CvSeq* icvCutContourRaster( CvSeq* current, CvMemStorage* storage, IplImage* image );
//create lists of segments of all contours from image
CvSeq* cvExtractSingleEdges( IplImage* image, //bw image - it's content will be destroyed by cvFindContours
CvMemStorage* storage )
{
CvMemStorage* tmp_storage = cvCreateChildMemStorage( storage );
CvSeq* contours = 0;
cvFindContours( image, tmp_storage, &contours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE );
cvZero( image );
//iterate through contours
//iterate through tree
CvSeq* current = contours;
int number = 0;
int level = 1;
CvSeq* output = 0;
CvSeq* tail_seq = 0;
//actually this loop can iterates through tree,
//but still we use CV_RETR_LIST it is not useful
while( current )
{
number++;
//get vertical list of segments for one contour
CvSeq* new_seq = icvCutContourRaster( current, storage, image );
//add this vertical list to horisontal list
if( new_seq )
{
if( tail_seq )
{
tail_seq->h_next = new_seq;
new_seq->h_prev = tail_seq;
tail_seq = new_seq;
}
else
{
output = tail_seq = new_seq;
}
}
//iteration through tree
if( current->v_next )
{
//goto child
current = current->v_next;
level++;
}
else
{
//go parent
while( !current->h_next )
{
current = current->v_prev;
level--;
if( !level ) break;
}
if( current ) //go brother
current = current->h_next;
}
}
//free temporary memstorage with initial contours
cvReleaseMemStorage( &tmp_storage );
return output;
}
//makes vertical list of segments for 1 contour
CvSeq* icvCutContourRaster( CvSeq* current, CvMemStorage* storage, IplImage* image /*tmp image*/)
{
//iplSet(image, 0 ); // this can cause double edges if two contours have common edge
// for example if object is circle with 1 pixel width
// to remove such problem - remove this iplSet
//approx contour by single edges
CvSeqReader reader;
CvSeqWriter writer;
int writing = 0;
cvStartReadSeq( current, &reader, 0 );
//below line just to avoid warning
cvStartWriteSeq( current->flags, sizeof(CvContour), sizeof(CvPoint), storage, &writer );
CvSeq* output = 0;
CvSeq* tail = 0;
//first pass through contour - compute number of branches at every point
int i;
for( i = 0; i < current->total; i++ )
{
CvPoint cur;
CV_READ_SEQ_ELEM( cur, reader );
//mark point
((uchar*)image->imageData)[image->widthStep * cur.y + cur.x]++;
assert( ((uchar*)image->imageData)[image->widthStep * cur.y + cur.x] != 255 );
}
//second pass - create separate edges
for( i = 0; i < current->total; i++ )
{
CvPoint cur;
CV_READ_SEQ_ELEM( cur, reader );
//get pixel at this point
uchar flag = image->imageData[image->widthStep * cur.y + cur.x];
if( flag != 255 && flag < 3) //
{
if(!writing)
{
cvStartWriteSeq( current->flags, sizeof(CvContour), sizeof(CvPoint), storage, &writer );
writing = 1 ;
}
//mark point
if( flag < 3 ) ((uchar*)image->imageData)[image->widthStep * cur.y + cur.x] = 255;
//add it to another seq
CV_WRITE_SEQ_ELEM( cur, writer );
}
else
{
//exclude this point from contour
if( writing )
{
CvSeq* newseq = cvEndWriteSeq( &writer );
writing = 0;
if( tail )
{
tail->v_next = newseq;
newseq->v_prev = tail;
tail = newseq;
}
else
{
output = tail = newseq;
}
}
}
}
if( writing ) //if were not self intersections
{
CvSeq* newseq = cvEndWriteSeq( &writer );
writing = 0;
if( tail )
{
tail->v_next = newseq;
newseq->v_prev = tail;
tail = newseq;
}
else
{
output = tail = newseq;
}
}
return output;
}
/*void icvCutContour( CvSeq* current, IplImage* image )
{
//approx contour by single edges
CvSeqReader reader;
CvSeqReader rev_reader;
cvStartReadSeq( current, &reader, 0 );
int64* cur_pt = (int64*)reader.ptr;
int64* prev_pt = (int64*)reader.prev_elem;
//search for point a in aba position
for( int i = 0; i < current->total; i++ )
{
CV_NEXT_SEQ_ELEM( sizeof(int64), reader );
//compare current reader pos element with old previous
if( prev_pt[0] == ((int64*)reader.ptr)[0] )
{
//return to prev pos
CV_PREV_SEQ_ELEM( sizeof(int64), reader );
//this point is end of edge
//start going both directions and collect edge
cvStartReadSeq( current, &rev_reader, 1 );
int pos = cvGetSeqReaderPos( &reader );
cvSetSeqReaderPos( &rev_reader, pos );
//walk in both directions
while(1);
}
int64* cur_pt = (int64*)reader.ptr;
int64* prev_pt = (int64*)reader.prev_elem;
}
}
*/
#endif /* WIN32 */

354
modules/legacy/src/face.cpp Normal file
View File

@@ -0,0 +1,354 @@
/*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*/
///////////////////////////////////////////////
//// Created by Khudyakov V.A. bober@gorodok.net
//////////////////////////////////////////////
#include "precomp.hpp"
#include "_facedetection.h"
Face::Face(FaceTemplate * lpFaceTemplate)
{
//init number of face elements;
m_lFaceFeaturesNumber = lpFaceTemplate->GetCount();
//init array of numbers of foundet face elements of each type
m_lplFaceFeaturesCount = new long[m_lFaceFeaturesNumber];
memset(m_lplFaceFeaturesCount,0,m_lFaceFeaturesNumber*sizeof(long));
//init array of ideal face features
m_lpIdealFace = new FaceFeature[m_lFaceFeaturesNumber];
//init array of founded features
m_lppFoundedFaceFeatures = new FaceFeature*[m_lFaceFeaturesNumber];
for (int i = 0;i < m_lFaceFeaturesNumber;i ++)
{
m_lppFoundedFaceFeatures[i] = (new FaceFeature[3*MAX_LAYERS]);
}
//set start weight 0
m_dWeight = 0;
}//Face::Face(FaceTemplate * lpFaceTemplate)
Face::~Face()
{
for (int i = 0;i < m_lFaceFeaturesNumber;i ++)
{
delete [] (m_lppFoundedFaceFeatures[i]);
}
delete [] m_lppFoundedFaceFeatures;
delete [] m_lplFaceFeaturesCount;
delete [] m_lpIdealFace;
}//Face::~Face()
#define UP_SCALE 1
#define DOWN_SCALE 2
////////////
//class RFace(rect based face)
////////////
RFace::RFace(FaceTemplate * lpFaceTemplate):Face(lpFaceTemplate)
{
//init ideal face
FaceFeature * lpTmp = lpFaceTemplate->GetFeatures();
for (int j = 0;j < m_lFaceFeaturesNumber;j ++)
{
CvRect * lpTmpRect = NULL;
lpTmpRect = new CvRect;
*lpTmpRect = *(CvRect*)lpTmp[j].GetContour();
m_lpIdealFace[j].SetContour( lpTmpRect );
m_lpIdealFace[j].SetWeight( lpTmp[j].GetWeight() );
m_lpIdealFace[j].SetFeature( lpTmp[j].isFaceFeature() );
}
m_bIsGenerated = false;
}//RFace::RFace(FaceTemplate * lpFaceTemplate)
RFace::~RFace()
{
}//RFace::~RFace()
inline bool RFace::isPointInRect(CvPoint p,CvRect rect)
{
if ( (p.x >= rect.x) && (p.y >= rect.y) && (p.x <= rect.x + rect.width) && (p.y <= rect.y + rect.height) )
return true;
return false;
}//inline bool RFace::isPointInRect(CvPoint,CvRect rect)
double RFace::GetWeight()
{
return m_dWeight;
}//double RFace::GetWeight()
bool RFace::CheckElem(void * lpCandidat,void * lpIdeal)
{
CvRect IdealRect = *(CvRect*)lpIdeal;
CvRect Rect = *(CvRect*)lpCandidat;
if (Rect.height > Rect.width)
return false;
long SizeIdeal = IdealRect.width*IdealRect.height;
long Size = Rect.width*Rect.height;
if ( (Size > SizeIdeal) || ( Size < (SizeIdeal/5) ) )
return false;
// CvRect UpRect;
// CvRect DownRect;
// ResizeRect(IdealRect,&UpRect,UP_SCALE,7);
// ResizeRect(IdealRect,&DownRect,DOWN_SCALE,7);
long x = Rect.x + cvRound(Rect.width/2);
long y = Rect.y + cvRound(Rect.height/2);
if ( isPointInRect(cvPoint(x,y),IdealRect) )
return true;
// if ( isPointInRect(cvPoint(Rect.x,Rect.y),UpRect) &&
// isPointInRect(cvPoint(Rect.x + Rect.width,Rect.y + Rect.height),UpRect ) &&
// isPointInRect(cvPoint(DownRect.x,DownRect.y),Rect) &&
// isPointInRect(cvPoint(DownRect.x + DownRect.width,DownRect.y + DownRect.height),Rect) )
// return true;
// if ( isPointInRect(cvPoint(Rect.x,Rect.y),IdealRect) &&
// isPointInRect(cvPoint(Rect.x + Rect.width,Rect.y + Rect.height),IdealRect ) )
// return true;
return false;
}//inline bool RFace::CheckElem(CvRect rect)
void RFace::CalculateError(FaceData * lpFaceData)
{
CvRect LeftEyeRect = lpFaceData->LeftEyeRect;
CvRect RightEyeRect = lpFaceData->RightEyeRect;
CvRect MouthRect = lpFaceData->MouthRect;
long LeftSquare = LeftEyeRect.width*LeftEyeRect.height;
long RightSquare = RightEyeRect.width*RightEyeRect.height;
long dy = LeftEyeRect.y - RightEyeRect.y;
long dx1 = LeftEyeRect.x + LeftEyeRect.width/2 - MouthRect.x;
long dx2 = RightEyeRect.x + RightEyeRect.width/2 - MouthRect.x - MouthRect.width;
lpFaceData->Error = (double)(LeftSquare - RightSquare)*(double)(LeftSquare - RightSquare)/((double)(LeftSquare + RightSquare)*(LeftSquare + RightSquare)) +
(double)(dy*dy)/((double)(LeftEyeRect.height + RightEyeRect.height)*(LeftEyeRect.height + RightEyeRect.height)) +
(double)(dx1*dx1)/((double)MouthRect.width*MouthRect.width) +
(double)(dx2*dx2)/((double)MouthRect.width*MouthRect.width);
}//void RFace::CalculateError(FaceData * lpFaceData)
#define MAX_ERROR 0xFFFFFFFF
void RFace::CreateFace(void * lpData)
{
FaceData Data;
double Error = MAX_ERROR;
double CurError = MAX_ERROR;
FaceData * lpFaceData = (FaceData*)lpData;
int im = 0;//mouth was find
int jl = 0;//left eye was find
int kr = 0;//right eye was find
long MouthNumber = 0;
long LeftEyeNumber = 0;
long RightEyeNumber = 0;
for (int i = 0;i < m_lplFaceFeaturesCount[0] + 1;i ++)
{
if ( !m_lplFaceFeaturesCount[0] )
Data.MouthRect = *(CvRect*)m_lpIdealFace[0].GetContour();
else
{
if ( i != m_lplFaceFeaturesCount[0] )
Data.MouthRect = *(CvRect*)m_lppFoundedFaceFeatures[0][i].GetContour();
im = 1;
}
for (int j = 0;j < m_lplFaceFeaturesCount[1] + 1;j ++)
{
if ( !m_lplFaceFeaturesCount[1] )
Data.LeftEyeRect = *(CvRect*)m_lpIdealFace[1].GetContour();
else
{
if (j != m_lplFaceFeaturesCount[1] )
Data.LeftEyeRect = *(CvRect*)m_lppFoundedFaceFeatures[1][j].GetContour();
jl = 1;
}
for (int k = 0;k < m_lplFaceFeaturesCount[2] + 1;k ++)
{
if ( !m_lplFaceFeaturesCount[2] )
Data.RightEyeRect = *(CvRect*)m_lpIdealFace[2].GetContour();
else
{
if (k != m_lplFaceFeaturesCount[2] )
Data.RightEyeRect = *(CvRect*)m_lppFoundedFaceFeatures[2][k].GetContour();
kr = 1;
}
CalculateError(&Data);
if ( (im + jl + kr) )
{
Error = Data.Error/(im + jl + kr);
}else
Error = MAX_ERROR;
if (CurError > Error)
{
CurError = Error;
MouthNumber = i;
LeftEyeNumber = j;
RightEyeNumber = k;
}
}
}
}
if ( m_lplFaceFeaturesCount[0] )
lpFaceData->MouthRect = *(CvRect*)m_lppFoundedFaceFeatures[0][MouthNumber].GetContour();
else
lpFaceData->MouthRect = *(CvRect*)m_lpIdealFace[0].GetContour();
if ( m_lplFaceFeaturesCount[1] )
lpFaceData->LeftEyeRect = *(CvRect*)m_lppFoundedFaceFeatures[1][LeftEyeNumber].GetContour();
else
lpFaceData->LeftEyeRect = *(CvRect*)m_lpIdealFace[1].GetContour();
if ( m_lplFaceFeaturesCount[2] )
lpFaceData->RightEyeRect = *(CvRect*)m_lppFoundedFaceFeatures[2][RightEyeNumber].GetContour();
else
lpFaceData->RightEyeRect = *(CvRect*)m_lpIdealFace[2].GetContour();
lpFaceData->Error = CurError;
}//void * RFace::CreateFace()
void RFace::Show(IplImage * Image)
{
for (int i = 0;i < m_lFaceFeaturesNumber;i ++)
{
if (m_lplFaceFeaturesCount[i])
{
for (int j = 0;j < m_lplFaceFeaturesCount[i];j ++)
{
CvRect rect = *(CvRect*)m_lppFoundedFaceFeatures[i][j].GetContour();
CvPoint p1 = cvPoint(rect.x,rect.y);
CvPoint p2 = cvPoint(rect.x + rect.width,rect.y + rect.height);
cvRectangle(Image,p1,p2,CV_RGB(255,0,0),1);
}
}
}
}//void RFace::Show(IplImage * Image)
void RFace::ShowIdeal(IplImage* Image)
{
for (int i = 0;i < m_lFaceFeaturesNumber;i ++)
{
CvRect Rect = *(CvRect*)m_lpIdealFace[i].GetContour();
CvPoint p1 = cvPoint(Rect.x,Rect.y);
CvPoint p2 = cvPoint(Rect.x + Rect.width,Rect.y + Rect.height);
cvRectangle(Image,p1,p2,CV_RGB(0,0,255),1);
}
}//void RFace::ShowIdeal(IplImage* Image)
inline void RFace::ResizeRect(CvRect Rect,CvRect * lpRect,long lDir,long lD)
{
if (lDir == UP_SCALE)
{
lpRect->x = Rect.x - lD;
lpRect->y = Rect.y - lD;
lpRect->width = Rect.width + 2*lD;
lpRect->height = Rect.height + 2*lD;
}
if (lDir == DOWN_SCALE)
{
lpRect->x = Rect.x + lD;
lpRect->y = Rect.y + lD;
if (Rect.width - 2*lD >= 0)
{
lpRect->width = Rect.width - 2*lD;
}else
lpRect->width = 0;
if (Rect.height - 2*lD >= 0)
{
lpRect->height = Rect.height - 2*lD;
}else
lpRect->height = 0;
}
}// inline void RFace::ResizeRect(CvRect * lpRect,long lDir,long lD)

136
modules/legacy/src/face.h Normal file
View File

@@ -0,0 +1,136 @@
/*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*/
///////////////////////////////////////////////
//// Created by Khudyakov V.A. bober@gorodok.net
//////////////////////////////////////////////
#ifndef __CVFACE_H__
#define __CVFACE_H__
#include "cvfacetemplate.h"
#define MAX_LAYERS 64
class Face
{
public:
Face(FaceTemplate * lpFaceTemplate);
virtual ~Face();
inline bool isFeature(void * lpElem);
virtual void Show(IplImage * /*Image*/){};
virtual void ShowIdeal(IplImage* /*Image*/){};
virtual void CreateFace(void * lpData) = 0;
virtual bool CheckElem(void * lpCandidat,void * lpIdeal) = 0;
virtual double GetWeight() = 0;
protected:
FaceFeature * m_lpIdealFace; // Ideal face definition.
long m_lFaceFeaturesNumber; // Total number of different face features .
long * m_lplFaceFeaturesCount; // Count of each feature found on this face.
FaceFeature ** m_lppFoundedFaceFeatures; // Features found on current face.
double m_dWeight;
};
inline bool Face::isFeature(void * lpElem)
{
for (int i = 0;i < m_lFaceFeaturesNumber;i ++)
{
void * lpIdeal = m_lpIdealFace[i].GetContour();
if ( CheckElem( lpElem,lpIdeal) )
{
if (m_lplFaceFeaturesCount[i] < 3*MAX_LAYERS)
{
double dWeight = m_lpIdealFace[i].GetWeight();
bool bIsFeature = m_lpIdealFace[i].isFaceFeature();
if (bIsFeature)
{
m_lppFoundedFaceFeatures[i][m_lplFaceFeaturesCount[i]].SetWeight(dWeight);
m_lppFoundedFaceFeatures[i][m_lplFaceFeaturesCount[i]].SetContour(lpElem);
m_lppFoundedFaceFeatures[i][m_lplFaceFeaturesCount[i]].SetFeature(bIsFeature);
m_lplFaceFeaturesCount[i] ++;
}
m_dWeight += dWeight;
if (bIsFeature)
return true;
}
}
}
return false;
}//inline bool RFace::isFeature(void * lpElem);
struct FaceData
{
CvRect LeftEyeRect;
CvRect RightEyeRect;
CvRect MouthRect;
double Error;
};//struct FaceData
class RFace:public Face
{
public:
RFace(FaceTemplate * lpFaceTemplate);
virtual ~RFace();
virtual bool CheckElem(void * lpCandidat,void * lpIdeal);
virtual void CreateFace(void * lpData);
virtual void Show(IplImage* Image);
virtual void ShowIdeal(IplImage* Image);
virtual double GetWeight();
private:
bool isPointInRect(CvPoint p,CvRect rect);
bool m_bIsGenerated;
void ResizeRect(CvRect Rect,CvRect * lpRect,long lDir,long lD);
void CalculateError(FaceData * lpFaceData);
};
#endif //__FACE_H__

View File

@@ -0,0 +1,486 @@
/*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*/
///////////////////////////////////////////////
//// Created by Khudyakov V.A. bober@gorodok.net
//////////////////////////////////////////////
// FaceDetection.cpp: implementation of the FaceDetection class.
//
//////////////////////////////////////////////////////////////////////
#include "precomp.hpp"
#include "_facedetection.h"
int CV_CDECL CompareContourRect(const void* el1, const void* el2, void* userdata);
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
FaceDetection::FaceDetection()
{
m_imgGray = NULL;
m_imgThresh = NULL;
m_mstgContours = NULL;
memset(m_seqContours, 0, sizeof(CvSeq*) * MAX_LAYERS);
m_mstgRects = NULL;
m_seqRects = NULL;
m_iNumLayers = 16;
assert(m_iNumLayers <= MAX_LAYERS);
m_pFaceList = new List();
m_bBoosting = false;
}// FaceDetection()
FaceDetection::~FaceDetection()
{
if (m_imgGray)
cvReleaseImage(&m_imgGray);
if (m_imgThresh)
cvReleaseImage(&m_imgThresh);
if (m_mstgContours)
cvReleaseMemStorage(&m_mstgContours);
if (m_mstgRects)
cvReleaseMemStorage(&m_mstgRects);
}// ~FaceDetection()
void FaceDetection::FindContours(IplImage* imgGray)
{
ReallocImage(&m_imgThresh, cvGetSize(imgGray), 1);
if (NULL == m_imgThresh)
return;
//
int iNumLayers = m_iNumLayers;
int iMinLevel = 0, iMaxLevel = 255, iStep = 255 / iNumLayers;
ThresholdingParam(imgGray, iNumLayers, iMinLevel, iMaxLevel, iStep);
// init
cvReleaseMemStorage(&m_mstgContours);
m_mstgContours = cvCreateMemStorage();
if (NULL == m_mstgContours)
return;
memset(m_seqContours, 0, sizeof(CvSeq*) * MAX_LAYERS);
cvReleaseMemStorage(&m_mstgRects);
m_mstgRects = cvCreateMemStorage();
if (NULL == m_mstgRects)
return;
m_seqRects = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvContourRect), m_mstgRects);
if (NULL == m_seqRects)
return;
// find contours
for (int l = iMinLevel, i = 0; l < iMaxLevel; l += iStep, i++)
{
cvThreshold(imgGray, m_imgThresh, (double)l, (double)255, CV_THRESH_BINARY);
if (cvFindContours(m_imgThresh, m_mstgContours, &m_seqContours[i], sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE))
AddContours2Rect(m_seqContours[i], l, i);
}
// sort rects
cvSeqSort(m_seqRects, CompareContourRect, NULL);
}// void FaceDetection::FindContours(IplImage* imgGray)
#define GIST_STEP 10
#define GIST_NUM (256 / GIST_STEP)
#define GIST_MIN 32
void FaceDetection::ThresholdingParam(IplImage *imgGray, int iNumLayers, int &iMinLevel, int &iMaxLevel, int &iStep)
{
assert(imgGray != NULL);
assert(imgGray->nChannels == 1);
int i, j;
// create gistogramm
uchar* buffImg = (uchar*)imgGray->imageData;
int gistImg[GIST_NUM + 1] = {0};
for (j = 0; j < imgGray->height; j ++)
{
for (i = 0; i < imgGray->width; i ++)
{
int ind = buffImg[i] / GIST_STEP;
gistImg[ind] ++;
}
buffImg += imgGray->widthStep;
}
// params
for (i = 0; i <= GIST_NUM; i ++)
{
if (gistImg[i] >= GIST_MIN)
break;
}
iMinLevel = i * GIST_STEP;
for (i = GIST_NUM; i >= 0; i --)
{
if (gistImg[i] >= GIST_MIN)
break;
}
iMaxLevel = i * GIST_STEP;
int dLevels = iMaxLevel - iMinLevel;
if (dLevels <= 0)
{
iMinLevel = 0;
iMaxLevel = 255;
}
else if (dLevels <= iNumLayers)
{
iMinLevel = iMaxLevel - iNumLayers;
if (iMinLevel < 0)
{
iMinLevel = 0;
iMaxLevel = iNumLayers;
}
}
iStep = (iMaxLevel - iMinLevel) / iNumLayers;
}// void FaceDetection::ThresholdingParam(IplImage *imgGray, int iNumLayers, int &iMinLevel, int &iMaxLevel, int &iStep)
#ifndef MAX_ERROR
#define MAX_ERROR 0xFFFFFFFF
#endif //MAX_ERROR
void FaceDetection::CreateResults(CvSeq * lpSeq)
{
Face * tmp;
double Max = 0;
double CurStat = 0;
FaceData tmpData;
if (m_bBoosting)
{
tmp = m_pFaceList->GetData();
tmp->CreateFace(&tmpData);
CvFace tmpFace;
tmpFace.MouthRect = tmpData.MouthRect;
tmpFace.LeftEyeRect = tmpData.LeftEyeRect;
tmpFace.RightEyeRect = tmpData.RightEyeRect;
cvSeqPush(lpSeq,&tmpFace);
}else
{
while ( (tmp = m_pFaceList->GetData()) != 0 )
{
CurStat = tmp->GetWeight();
if (CurStat > Max)
Max = CurStat;
}
while ( (tmp = m_pFaceList->GetData()) != 0 )
{
tmp->CreateFace(&tmpData);
CurStat = tmp->GetWeight();
if (CurStat == Max)
{
CvFace tmpFace;
tmpFace.MouthRect = tmpData.MouthRect;
tmpFace.LeftEyeRect = tmpData.LeftEyeRect;
tmpFace.RightEyeRect = tmpData.RightEyeRect;
cvSeqPush(lpSeq,&tmpFace);
}
}
}
}// void FaceDetection::DrawResult(IplImage* img)
void FaceDetection::ResetImage()
{
delete m_pFaceList;
m_pFaceList = new List();
}//FaceDetection::ResetImage
void FaceDetection::AddContours2Rect(CvSeq *seq, int color, int iLayer)
{
assert(m_mstgRects != NULL);
assert(m_seqRects != NULL);
CvContourRect cr;
for (CvSeq* external = seq; external; external = external->h_next)
{
cr.r = cvContourBoundingRect(external, 1 );
cr.pCenter.x = cr.r.x + cr.r.width / 2;
cr.pCenter.y = cr.r.y + cr.r.height / 2;
cr.iNumber = iLayer;
cr.iType = 6;
cr.iFlags = 0;
cr.seqContour = external;
cr.iContourLength = external->total;
cr.iColor = color;
cvSeqPush(m_seqRects, &cr);
for (CvSeq* internal = external->v_next; internal; internal = internal->h_next)
{
cr.r = cvContourBoundingRect(internal, 0);
cr.pCenter.x = cr.r.x + cr.r.width / 2;
cr.pCenter.y = cr.r.y + cr.r.height / 2;
cr.iNumber = iLayer;
cr.iType = 12;
cr.iFlags = 0;
cr.seqContour = internal;
cr.iContourLength = internal->total;
cr.iColor = color;
cvSeqPush(m_seqRects, &cr);
}
}
}// void FaceDetection::AddContours2Rect(CvSeq *seq, int color, int iLayer)
int CV_CDECL CompareContourRect(const void* el1, const void* el2, void* /*userdata*/)
{
return (((CvContourRect*)el1)->pCenter.y - ((CvContourRect*)el2)->pCenter.y);
}// int CV_CDECL CompareContourRect(const void* el1, const void* el2, void* userdata)
void FaceDetection::FindFace(IplImage *img)
{
// find all contours
FindContours(img);
//
ResetImage();
if (m_bBoosting)
PostBoostingFindCandidats(img);
else
FindCandidats();
}// void FaceDetection::FindFace(IplImage *img)
void FaceDetection::FindCandidats()
{
bool bFound1 = false;
MouthFaceTemplate * lpFaceTemplate1;
RFace * lpFace1;
bool bInvalidRect1 = false;
CvRect * lpRect1 = NULL;
for (int i = 0; i < m_seqRects->total; i++)
{
CvContourRect* pRect = (CvContourRect*)cvGetSeqElem(m_seqRects, i);
CvRect rect = pRect->r;
if (rect.width >= 2*rect.height)
{
lpFaceTemplate1 = new MouthFaceTemplate(3,rect,3*(double)rect.width/(double)4,
3*(double)rect.width/(double)4,
(double)rect.width/(double)2,
(double)rect.width/(double)2);
lpFace1 = new RFace(lpFaceTemplate1);
for (int j = 0; j < m_seqRects->total; j++)
{
CvContourRect* pRect = (CvContourRect*)cvGetSeqElem(m_seqRects, j);
if ( !bInvalidRect1 )
{
lpRect1 = NULL;
lpRect1 = new CvRect();
*lpRect1 = pRect->r;
}else
{
delete lpRect1;
lpRect1 = new CvRect();
*lpRect1 = pRect->r;
}
if ( lpFace1->isFeature(lpRect1) )
{
bFound1 = true;
bInvalidRect1 = false;
}else
bInvalidRect1 = true;
}
if (bFound1)
{
m_pFaceList->AddElem(lpFace1);
bFound1 = false;
lpFace1 = NULL;
}else
{
delete lpFace1;
lpFace1 = NULL;
}
delete lpFaceTemplate1;
}
}
}
void FaceDetection::PostBoostingFindCandidats(IplImage * FaceImage)
{
BoostingFaceTemplate * lpFaceTemplate1;
RFace * lpFace1;
bool bInvalidRect1 = false;
CvRect * lpRect1 = NULL;
if ( ( !FaceImage->roi ) )
lpFaceTemplate1 = new BoostingFaceTemplate(3,cvRect(0,0,FaceImage->width,FaceImage->height));
else
lpFaceTemplate1 = new BoostingFaceTemplate(3,cvRect(FaceImage->roi->xOffset,FaceImage->roi->yOffset,
FaceImage->roi->width,FaceImage->roi->height));
lpFace1 = new RFace(lpFaceTemplate1);
for (int i = 0; i < m_seqRects->total; i++)
{
CvContourRect* pRect = (CvContourRect*)cvGetSeqElem(m_seqRects, i);
if ( !bInvalidRect1 )
{
lpRect1 = NULL;
lpRect1 = new CvRect();
*lpRect1 = pRect->r;
}else
{
delete lpRect1;
lpRect1 = new CvRect();
*lpRect1 = pRect->r;
}
if ( lpFace1->isFeature(lpRect1) )
{
//bFound1 = true;
bInvalidRect1 = false;
}else
bInvalidRect1 = true;
}
m_pFaceList->AddElem(lpFace1);
delete lpFaceTemplate1;
}//void FaceDetection::PostBoostingFindCandidats(IplImage * FaceImage)
/////////////////////////
//class Face
//////
//List Class
/////
ListElem::ListElem()
{
m_pNext = this;
m_pPrev = this;
m_pFace = NULL;
}///ListElem::ListElem()
ListElem::ListElem(Face * pFace,ListElem * pHead)
{
m_pNext = pHead;
m_pPrev = pHead->m_pPrev;
pHead->m_pPrev->m_pNext = this;
pHead->m_pPrev = this;
m_pFace = pFace;
}//ListElem::ListElem(Face * pFace)
ListElem::~ListElem()
{
delete m_pFace;
m_pNext->m_pPrev = m_pPrev;
m_pPrev->m_pNext = m_pNext;
}//ListElem::~ListElem()
List::List()
{
m_pHead = new ListElem();
m_FacesCount = 0;
m_pCurElem = m_pHead;
}//List::List()
List::~List()
{
void * tmp;
while((tmp = m_pHead->m_pNext->m_pFace) != 0)
delete m_pHead->m_pNext;
delete m_pHead;
}//List::~List()
int List::AddElem(Face * pFace)
{
new ListElem(pFace,m_pHead);
return m_FacesCount++;
}//List::AddElem(Face * pFace)
Face * List::GetData()
{
m_pCurElem = m_pCurElem->m_pNext;
return m_pCurElem->m_pFace;
}//Face * List::GetData()

View File

@@ -0,0 +1,100 @@
// FaceDetection.h: interface for the FaceDetection class.
//
//////////////////////////////////////////////////////////////////////
#ifndef _CVFACEDETECTION_H_
#define _CVFACEDETECTION_H_
#include "cvfacetemplate.h"
#include "cvface.h"
#include "cvboostingtemplate.h"
typedef struct CvContourRect
{
int iNumber; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int iType; //<2F><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int iFlags; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
CvSeq *seqContour; //<2F><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int iContourLength; //<2F><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
CvRect r; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
CvPoint pCenter; // center of rect
int iColor;// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
} CvContourRect;
//class Face;
class ListElem
{
public:
ListElem();
ListElem(Face * pFace,ListElem * pHead);
virtual ~ListElem();
ListElem * m_pNext;
ListElem * m_pPrev;
Face * m_pFace;
};//class ListElem
class List
{
public:
List();
int AddElem(Face * pFace);
virtual ~List();
Face* GetData();
long m_FacesCount;
private:
ListElem * m_pHead;
ListElem * m_pCurElem;
};//class List
class FaceDetection
{
public:
void FindFace(IplImage* img);
void CreateResults(CvSeq * lpSeq);
FaceDetection();
virtual ~FaceDetection();
void SetBoosting(bool bBoosting) {m_bBoosting = bBoosting;}
bool isPostBoosting() {return m_bBoosting;}
protected:
IplImage* m_imgGray;
IplImage* m_imgThresh;
int m_iNumLayers;
CvMemStorage* m_mstgContours;
CvSeq* m_seqContours[MAX_LAYERS];
CvMemStorage* m_mstgRects;
CvSeq* m_seqRects;
bool m_bBoosting;
List * m_pFaceList;
protected:
void ResetImage();
void FindContours(IplImage* imgGray);
void AddContours2Rect(CvSeq* seq, int color, int iLayer);
void ThresholdingParam(IplImage* imgGray, int iNumLayers, int& iMinLevel, int& iMaxLevel, int& iStep);
void FindCandidats();
void PostBoostingFindCandidats(IplImage * FaceImage);
};
inline void ReallocImage(IplImage** ppImage, CvSize sz, long lChNum)
{
IplImage* pImage;
if( ppImage == NULL )
return;
pImage = *ppImage;
if( pImage != NULL )
{
if (pImage->width != sz.width || pImage->height != sz.height || pImage->nChannels != lChNum)
cvReleaseImage( &pImage );
}
if( pImage == NULL )
pImage = cvCreateImage( sz, IPL_DEPTH_8U, lChNum);
*ppImage = pImage;
};
#endif // !defined(AFX_FACEDETECTION_H__55865033_D8E5_4DD5_8925_34C2285BB1BE__INCLUDED_)

View File

@@ -0,0 +1,86 @@
/*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*/
///////////////////////////////////////////////
//// Created by Khudyakov V.A. bober@gorodok.net
//////////////////////////////////////////////
#include "precomp.hpp"
#include "_facedetection.h"
///class FaceFeature
FaceFeature::FaceFeature(double dWeight,void * lpContour,bool bIsFeature)
{
m_lpContour = lpContour;
m_dWeight = dWeight;
m_bIsFaceFeature = bIsFeature;
}//FaceFeature::FaceFeature(long lWeight,void * lpContour)
FaceFeature::~FaceFeature()
{
if (m_lpContour)
delete (char*)m_lpContour;
}//FaceFeature::~FaceFeature()
FaceFeature::FaceFeature()
{
m_lpContour = NULL;
m_dWeight = 0;
m_bIsFaceFeature = false;
}
////class FaceTemplate
FaceTemplate::~FaceTemplate()
{
delete [] m_lpFeaturesList;
}//FaceTemplate::~FaceTemplate()
/////
//class RFaceTemplate
/////
MouthFaceTemplate::~MouthFaceTemplate()
{
}//RFaceTemplate::~RFaceTemplate()

View File

@@ -0,0 +1,202 @@
/*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*/
///////////////////////////////////////////////
//// Created by Khudyakov V.A. bober@gorodok.net
//////////////////////////////////////////////
#ifndef __CVFACETEMPLATE_H__
#define __CVFACETEMPLATE_H__
class FaceFeature
{
public:
FaceFeature(double dWeight,void * lpContour,bool bIsFeature);
FaceFeature();
virtual ~FaceFeature();
inline bool isFaceFeature();
inline void * GetContour();
inline double GetWeight();
inline void SetContour(void * lpContour);
inline void SetWeight(double dWeight);
inline void SetFeature(bool bIsFeature);
private:
double m_dWeight;
void * m_lpContour;
bool m_bIsFaceFeature;
};//class FaceFeature
inline void FaceFeature::SetFeature(bool bIsFeature)
{
m_bIsFaceFeature = bIsFeature;
}
inline bool FaceFeature::isFaceFeature()
{
return m_bIsFaceFeature;
}//inline bool FaceFeature::isFaceFeature()
inline void * FaceFeature::GetContour()
{
return m_lpContour;
}//inline void * FaceFeature::GetContour()
inline double FaceFeature::GetWeight()
{
return m_dWeight;
}//inline long FaceFeature::GetWeight()
inline void FaceFeature::SetContour(void * lpContour)
{
m_lpContour = lpContour;
}//inline void FaceFeature::SetContour(void * lpContour)
inline void FaceFeature::SetWeight(double dWeight)
{
m_dWeight = dWeight;
}//inline void FaceFeature::SetWeight(double * dWeight)
class FaceTemplate
{
public:
FaceTemplate(long lFeatureCount) {m_lFeturesCount = lFeatureCount; m_lpFeaturesList = new FaceFeature[lFeatureCount];};
virtual ~FaceTemplate();
inline long GetCount();
inline FaceFeature * GetFeatures();
protected:
FaceFeature * m_lpFeaturesList;
private:
long m_lFeturesCount;
};//class FaceTemplate
inline long FaceTemplate::GetCount()
{
return m_lFeturesCount;
}//inline long FaceTemplate::GetCount()
inline FaceFeature * FaceTemplate::GetFeatures()
{
return m_lpFeaturesList;
}//inline FaceFeature * FaceTemplate::GetFeatures()
////////////
//class RFaceTemplate
///////////
class MouthFaceTemplate:public FaceTemplate
{
public:
inline MouthFaceTemplate(long lNumber,CvRect rect,double dEyeWidth,double dEyeHeight,double dDistanceBetweenEye,double dDistanceEyeAboveMouth);
~MouthFaceTemplate();
};//class MouthFaceTemplate:public FaceTemplate
inline MouthFaceTemplate::MouthFaceTemplate(long lNumber,CvRect rect,double dEyeWidth,double dEyeHeight,
double dDistanceBetweenEye,double dDistanceEyeAboveMouth):FaceTemplate(lNumber)
{
CvRect MouthRect = rect;
CvRect LeftEyeRect = cvRect(cvRound(rect.x - (dEyeWidth + dDistanceBetweenEye/(double)2 - (double)rect.width/(double)2)),
cvRound(rect.y - dDistanceEyeAboveMouth - dEyeHeight),
cvRound(dEyeWidth),
cvRound(dEyeHeight) );
CvRect RightEyeRect = cvRect(cvRound(rect.x + (double)rect.width/(double)2 + dDistanceBetweenEye/(double)2),
cvRound(rect.y - dDistanceEyeAboveMouth - dEyeHeight),
cvRound(dEyeWidth),
cvRound(dEyeHeight) );
// CvRect NoseRect = cvRect(cvRound(rect.x + (double)rect.width/(double)4),
// cvRound(rect.y - (double)rect.width/(double)2 - (double)rect.height/(double)4),
// cvRound((double)rect.width/(double)2),
// cvRound((double)rect.width/(double)2) );
/*
CvRect CheenRect = cvRect(rect.x,rect.y + 3*rect.height/2,rect.width,rect.height);
*/
CvRect * lpMouthRect = new CvRect();
*lpMouthRect = MouthRect;
m_lpFeaturesList[0].SetContour(lpMouthRect);
m_lpFeaturesList[0].SetWeight(1);
m_lpFeaturesList[0].SetFeature(false);
CvRect * lpLeftEyeRect = new CvRect();
*lpLeftEyeRect = LeftEyeRect;
m_lpFeaturesList[1].SetContour(lpLeftEyeRect);
m_lpFeaturesList[1].SetWeight(1);
m_lpFeaturesList[1].SetFeature(true);
CvRect * lpRightEyeRect = new CvRect();
*lpRightEyeRect = RightEyeRect;
m_lpFeaturesList[2].SetContour(lpRightEyeRect);
m_lpFeaturesList[2].SetWeight(1);
m_lpFeaturesList[2].SetFeature(true);
// CvRect * lpNoseRect = new CvRect();
// *lpNoseRect = NoseRect;
// m_lpFeaturesList[3].SetContour(lpNoseRect);
// m_lpFeaturesList[3].SetWeight(0);
// m_lpFeaturesList[3].SetFeature(true);
/* CvRect * lpCheenRect = new CvRect();
*lpCheenRect = CheenRect;
m_lpFeaturesList[4].SetContour(lpCheenRect);
m_lpFeaturesList[4].SetWeight(1);
m_lpFeaturesList[4].SetFeature(false);
*/
};//constructor MouthFaceTemplate(long lNumFeatures,CvRect rect,double dEyeWidth,double dEyeHeight,double dDistanceBetweenEye,double dDistanceEyeAboveMouth);
#endif//__FACETEMPLATE_H__

View File

@@ -0,0 +1,68 @@
/*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*/
///////////////////////////////////////////////
//// Created by Khudyakov V.A. bober@gorodok.net
//////////////////////////////////////////////
#include "precomp.hpp"
#include "_facedetection.h"
CvSeq * cvFindFace(IplImage * Image,CvMemStorage* lpStorage)
{
FaceDetection FD;
FD.SetBoosting(false);
FD.FindFace(Image);
CvSeq * lpSeq = cvCreateSeq(0,sizeof(*lpSeq),sizeof(CvFace),lpStorage);
FD.CreateResults(lpSeq);
return lpSeq;
}//cvFindFace(IplImage * Image)
CvSeq * cvPostBoostingFindFace(IplImage * Image,CvMemStorage* lpStorage)
{
FaceDetection FD;
FD.SetBoosting(true);
FD.FindFace(Image);
CvSeq * lpSeq = cvCreateSeq(0,sizeof(*lpSeq),sizeof(CvFace),lpStorage);
FD.CreateResults(lpSeq);
return lpSeq;
}//cvPostBoostingFindFace(IplImage * Image)

View File

@@ -0,0 +1,634 @@
/*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"
#define _CV_NORM_L2(a) (float)(icvSqrt32f(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]))
#define _CV_NORM_L22(a) (float)(a[0]*a[0] + a[1]*a[1] + a[2]*a[2])
/****************************************************************************************\
find region where hand is (for gesture recognition)
flag = 0 (use left bucket) flag = 1 (use right bucket)
\****************************************************************************************/
static CvStatus CV_STDCALL
icvFindHandRegion( CvPoint3D32f * points, int count,
CvSeq * indexs,
float *line, CvSize2D32f size, int flag,
CvPoint3D32f * center,
CvMemStorage * storage, CvSeq ** numbers )
{
/* IppmVect32f sub, cros; */
float *sub, *cros;
CvSeqWriter writer;
CvSeqReader reader;
CvStatus status;
int nbins = 20, i, l, i_point, left, right;
int *bin_counts = 0; // pointer to the point's counter in the bickets
int low_count; // low threshold
CvPoint *tmp_number = 0, *pt;
float value, vmin, vmax, vl, bsize, vc;
float hand_length, hand_length2, hand_left, hand_right;
float threshold, threshold2;
float *vv = 0;
float a[3];
status = CV_OK;
hand_length = size.width;
hand_length2 = hand_length / 2;
threshold = (float) (size.height * 3 / 5.);
threshold2 = threshold * threshold;
/* low_count = count/nbins; */
low_count = (int) (count / 60.);
assert( points != NULL && line != NULL );
if( points == NULL || line == NULL )
return CV_NULLPTR_ERR;
assert( count > 5 );
if( count < 5 )
return CV_BADFLAG_ERR;
assert( flag == 0 || flag == 1 );
if( flag != 0 && flag != 1 )
return CV_BADFLAG_ERR;
/* create vectors */
sub = icvCreateVector_32f( 3 );
cros = icvCreateVector_32f( 3 );
if( sub == NULL || cros == NULL )
return CV_OUTOFMEM_ERR;
/* alloc memory for the point's projections on the line */
vv = (float *) cvAlloc( count * sizeof( float ));
if( vv == NULL )
return CV_OUTOFMEM_ERR;
/* alloc memory for the point's counter in the bickets */
bin_counts = (int *) cvAlloc( nbins * sizeof( int ));
if( bin_counts == NULL )
{
status = CV_OUTOFMEM_ERR;
goto M_END;
}
memset( bin_counts, 0, nbins * sizeof( int ));
cvStartReadSeq( indexs, &reader, 0 );
/* alloc memory for the temporale point's numbers */
tmp_number = (CvPoint *) cvAlloc( count * sizeof( CvPoint ));
if( tmp_number == NULL )
{
status = CV_OUTOFMEM_ERR;
goto M_END;
}
/* find min and max point's projection on the line */
vmin = 1000;
vmax = -1000;
i_point = 0;
for( i = 0; i < count; i++ )
{
/*
icvSubVector_32f ((IppmVect32f )&points[i], (IppmVect32f )&line[3], sub, 3);
icvCrossProduct2L_32f ((IppmVect32f )&line[0], sub, cros);
*/
sub[0] = points[i].x - line[3];
sub[1] = points[i].y - line[4];
sub[2] = points[i].z - line[5];
a[0] = sub[0] * line[1] - sub[1] * line[0];
a[1] = sub[1] * line[2] - sub[2] * line[1];
a[2] = sub[2] * line[0] - sub[0] * line[2];
/* if(IPPI_NORM_L22 ( cros ) < threshold2) */
if( _CV_NORM_L22( a ) < threshold2 )
{
value = (float)icvDotProduct_32f( sub, &line[0], 3 );
if( value > vmax )
vmax = value;
if( value < vmin )
vmin = value;
vv[i_point] = value;
pt = (CvPoint*)cvGetSeqElem( indexs, i );
tmp_number[i_point] = *pt;
i_point++;
}
}
/* compute the length of one bucket */
vl = vmax - vmin;
bsize = vl / nbins;
/* compute the number of points in each bucket */
for( i = 0; i < i_point; i++ )
{
l = cvRound( (vv[i] - vmin) / bsize );
bin_counts[l]++;
}
*numbers = cvCreateSeq( CV_SEQ_POINT_SET, sizeof( CvSeq ), sizeof( CvPoint ), storage );
assert( numbers != 0 );
if( numbers == NULL )
{
status = CV_OUTOFMEM_ERR;
goto M_END;
}
cvStartAppendToSeq( *numbers, &writer );
if( flag == 0 )
{
/* find the leftmost bucket */
for( l = 0; l < nbins; l++ )
{
if( bin_counts[l] > low_count )
break;
}
left = l;
/* compute center point of the left hand */
hand_left = vmin + left * bsize;
vc = hand_left + hand_length2;
hand_right = hand_left + hand_length;
}
else
{
/* find the rightmost bucket */
for( l = nbins - 1; l >= 0; l-- )
{
if( bin_counts[l] > low_count )
break;
}
right = l;
/* compute center point of the right hand */
hand_right = vmax - (nbins - right - 1) * bsize;
vc = hand_right - hand_length2;
hand_left = hand_right - hand_length;
}
icvScaleVector_32f( &line[0], sub, 3, vc );
icvAddVector_32f( &line[3], sub, (float *) center, 3 );
/* select hand's points and calculate mean value */
//ss.x = ss.y = ss.z = 0;
for( l = 0; l < i_point; l++ )
{
if( vv[l] >= hand_left && vv[l] <= hand_right )
{
CV_WRITE_SEQ_ELEM( tmp_number[l], writer );
}
}
cvEndWriteSeq( &writer );
M_END:
if( tmp_number != NULL )
cvFree( &tmp_number );
if( bin_counts != NULL )
cvFree( &bin_counts );
if( vv != NULL )
cvFree( &vv );
if( sub != NULL ) icvDeleteVector (sub);
if( cros != NULL ) icvDeleteVector (cros);
return status;
}
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
#define _CV_NORM_L31(a) (float)(icvSqrt32f(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]))
#define _CV_NORM_L32(a) (float)(a[0]*a[0] + a[1]*a[1] + a[2]*a[2])
/****************************************************************************************\
find region where hand is (for gesture recognition)
flag = 0 (use left bucket) flag = 1 (use right bucket)
\****************************************************************************************/
static CvStatus CV_STDCALL
icvFindHandRegionA( CvPoint3D32f * points, int count,
CvSeq * indexs,
float *line, CvSize2D32f size, int jc,
CvPoint3D32f * center,
CvMemStorage * storage, CvSeq ** numbers )
{
/* IppmVect32f sub, cros; */
float *sub, *cros;
float eps = (float) 0.01;
CvSeqWriter writer;
CvSeqReader reader;
CvStatus status;
float gor[3] = { 1, 0, 0 };
float ver[3] = { 0, 1, 0 };
int nbins = 20, i, l, i_point, left, right, jmin, jmax, jl;
int j_left, j_right;
int *bin_counts = 0; // pointer to the point's counter in the bickets
// int *bin_countsj = 0; // pointer to the index's counter in the bickets
int low_count; // low threshold
CvPoint *tmp_number = 0, *pt;
float value, vmin, vmax, vl, bsize, bsizej, vc, vcl, vcr;
double v_ver, v_gor;
float hand_length, hand_length2, hand_left, hand_right;
float threshold, threshold2;
float *vv = 0;
float a[3];
char log;
status = CV_OK;
hand_length = size.width;
hand_length2 = hand_length / 2;
threshold = (float) (size.height * 3 / 5.);
threshold2 = threshold * threshold;
/* low_count = count/nbins; */
low_count = (int) (count / 60.);
assert( points != NULL && line != NULL );
if( points == NULL || line == NULL )
return CV_NULLPTR_ERR;
assert( count > 5 );
if( count < 5 )
return CV_BADFLAG_ERR;
/* create vectors */
sub = icvCreateVector_32f( 3 );
cros = icvCreateVector_32f( 3 );
if( sub == NULL || cros == NULL )
return CV_OUTOFMEM_ERR;
/* alloc memory for the point's projections on the line */
vv = (float *) cvAlloc( count * sizeof( float ));
if( vv == NULL )
return CV_OUTOFMEM_ERR;
/* alloc memory for the point's counter in the bickets */
bin_counts = (int *) cvAlloc( nbins * sizeof( int ));
if( bin_counts == NULL )
{
status = CV_OUTOFMEM_ERR;
goto M_END;
}
memset( bin_counts, 0, nbins * sizeof( int ));
/* alloc memory for the point's counter in the bickets */
// bin_countsj = (int*) icvAlloc(nbins*sizeof(int));
// if(bin_countsj == NULL) {status = CV_OUTOFMEM_ERR; goto M_END;}
// memset(bin_countsj,0,nbins*sizeof(int));
cvStartReadSeq( indexs, &reader, 0 );
/* alloc memory for the temporale point's numbers */
tmp_number = (CvPoint *) cvAlloc( count * sizeof( CvPoint ));
if( tmp_number == NULL )
{
status = CV_OUTOFMEM_ERR;
goto M_END;
}
/* find min and max point's projection on the line */
vmin = 1000;
vmax = -1000;
jmin = 1000;
jmax = -1000;
i_point = 0;
for( i = 0; i < count; i++ )
{
/*
icvSubVector_32f ((IppmVect32f )&points[i], (IppmVect32f )&line[3], sub, 3);
icvCrossProduct2L_32f ((IppmVect32f )&line[0], sub, cros);
*/
sub[0] = points[i].x - line[3];
sub[1] = points[i].y - line[4];
sub[2] = points[i].z - line[5];
// if(fabs(sub[0])<eps||fabs(sub[1])<eps||fabs(sub[2])<eps) continue;
a[0] = sub[0] * line[1] - sub[1] * line[0];
a[1] = sub[1] * line[2] - sub[2] * line[1];
a[2] = sub[2] * line[0] - sub[0] * line[2];
v_gor = icvDotProduct_32f( gor, &line[0], 3 );
v_ver = icvDotProduct_32f( ver, &line[0], 3 );
if( v_ver > v_gor )
log = true;
else
log = false;
/* if(IPPI_NORM_L22 ( cros ) < threshold2) */
/*
if(fabs(a[0])<eps && fabs(a[1])<eps && fabs(a[2])<eps)
{
icvDotProduct_32f( sub, &line[0], 3, &value);
if(value > vmax) vmax = value;
if(value < vmin) vmin = value;
vv[i_point] = value;
pt = (CvPoint* )icvGetSeqElem ( indexs, i, 0);
if(pt->x > jmax) jmax = pt->x;
if(pt->x < jmin) jmin = pt->x;
tmp_number[i_point] = *pt;
i_point++;
}
else
*/
{
if( _CV_NORM_L32( a ) < threshold2 )
{
value = (float)icvDotProduct_32f( sub, &line[0], 3 );
if( value > vmax )
vmax = value;
if( value < vmin )
vmin = value;
vv[i_point] = value;
pt = (CvPoint*)cvGetSeqElem( indexs, i );
if( !log )
{
if( pt->x > jmax )
jmax = pt->x;
if( pt->x < jmin )
jmin = pt->x;
}
else
{
if( pt->y > jmax )
jmax = pt->y;
if( pt->y < jmin )
jmin = pt->y;
}
tmp_number[i_point] = *pt;
i_point++;
}
}
}
/* compute the length of one bucket along the line */
vl = vmax - vmin;
/* examining on the arm's existence */
if( vl < eps )
{
*numbers = NULL;
status = CV_OK;
goto M_END;
}
bsize = vl / nbins;
/* compute the number of points in each bucket along the line */
for( i = 0; i < i_point; i++ )
{
l = cvRound( (vv[i] - vmin) / bsize );
bin_counts[l]++;
}
/* compute the length of one bucket along the X axe */
jl = jmax - jmin;
if( jl <= 1 )
{
*numbers = NULL;
status = CV_OK;
goto M_END;
}
bsizej = (float) (jl / (nbins + 0.));
/* compute the number of points in each bucket along the X axe */
// for(i=0;i<i_point;i++)
// {
// l = cvRound((tmp_number[i].x - jmin)/bsizej);
// bin_countsj[l]++;
// }
left = right = -1;
/* find the leftmost and the rightmost buckets */
for( l = 0; l < nbins; l++ )
{
if( bin_counts[l] > low_count && left == -1 )
left = l;
else if( bin_counts[l] > low_count && left >= 0 )
right = l;
}
/* compute center point of the left hand */
if( left == -1 && right == -1 )
{
*numbers = NULL;
status = CV_OK;
goto M_END;
}
hand_left = vmin + left * bsize;
j_left = (int) (jmin + left * bsizej);
vcl = hand_left + hand_length2;
/* compute center point of the right hand */
hand_right = vmax - (nbins - right - 1) * bsize;
vcr = hand_right - hand_length2;
j_right = (int) (jmax - (nbins - right - 1) * bsizej);
j_left = abs( j_left - jc );
j_right = abs( j_right - jc );
if( j_left <= j_right )
{
hand_right = hand_left + hand_length;
vc = vcl;
}
else
{
hand_left = hand_right - hand_length;
vc = vcr;
}
icvScaleVector_32f( &line[0], sub, 3, vc );
icvAddVector_32f( &line[3], sub, (float *) center, 3 );
/* select hand's points and calculate mean value */
*numbers = cvCreateSeq( CV_SEQ_POINT_SET, sizeof( CvSeq ), sizeof( CvPoint ), storage );
assert( *numbers != 0 );
if( *numbers == NULL )
{
status = CV_OUTOFMEM_ERR;
goto M_END;
}
cvStartAppendToSeq( *numbers, &writer );
for( l = 0; l < i_point; l++ )
{
if( vv[l] >= hand_left && vv[l] <= hand_right )
{
CV_WRITE_SEQ_ELEM( tmp_number[l], writer );
}
}
cvEndWriteSeq( &writer );
M_END:
if( tmp_number != NULL )
cvFree( &tmp_number );
// if(bin_countsj != NULL) cvFree( &bin_countsj );
if( bin_counts != NULL )
cvFree( &bin_counts );
if( vv != NULL )
cvFree( &vv );
if( sub != NULL ) icvDeleteVector (sub);
if( cros != NULL ) icvDeleteVector (cros);
return status;
}
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvFindHandRegion
// Purpose: finds hand region in range image data
// Context:
// Parameters:
// points - pointer to the input point's set.
// count - the number of the input points.
// indexs - pointer to the input sequence of the point's indexes
// line - pointer to the 3D-line
// size - size of the hand in meters
// flag - hand direction's flag (0 - left, -1 - right,
// otherwise j-index of the initial image center)
// center - pointer to the output hand center
// storage - pointer to the memory storage
// numbers - pointer to the output sequence of the point's indexes inside
// hand region
//
// Notes:
//F*/
CV_IMPL void
cvFindHandRegion( CvPoint3D32f * points, int count,
CvSeq * indexs,
float *line, CvSize2D32f size, int flag,
CvPoint3D32f * center, CvMemStorage * storage, CvSeq ** numbers )
{
if(flag == 0 || flag == -1)
{
IPPI_CALL( icvFindHandRegion( points, count, indexs, line, size, -flag,
center, storage, numbers ));
}
else
IPPI_CALL( icvFindHandRegionA( points, count, indexs, line, size, flag,
center, storage, numbers ));
}
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvFindHandRegionA
// Purpose: finds hand region in range image data
// Context:
// Parameters:
// points - pointer to the input point's set.
// count - the number of the input points.
// indexs - pointer to the input sequence of the point's indexes
// line - pointer to the 3D-line
// size - size of the hand in meters
// jc - j-index of the initial image center
// center - pointer to the output hand center
// storage - pointer to the memory storage
// numbers - pointer to the output sequence of the point's indexes inside
// hand region
//
// Notes:
//F*/
CV_IMPL void
cvFindHandRegionA( CvPoint3D32f * points, int count,
CvSeq * indexs,
float *line, CvSize2D32f size, int jc,
CvPoint3D32f * center, CvMemStorage * storage, CvSeq ** numbers )
{
IPPI_CALL( icvFindHandRegionA( points, count, indexs, line, size, jc,
center, storage, numbers ));
}

1700
modules/legacy/src/hmm.cpp Normal file

File diff suppressed because it is too large Load Diff

1151
modules/legacy/src/hmm1d.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,634 @@
/*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"
//*F///////////////////////////////////////////////////////////////////////////////////////
// Name: icvImgToObs_DCT_8u32f_C1R
// Purpose: The function takes as input an image and returns the sequnce of observations
// to be used with an embedded HMM; Each observation is top-left block of DCT
// coefficient matrix.
// Context:
// Parameters: img - pointer to the original image ROI
// imgStep - full row width of the image in bytes
// roi - width and height of ROI in pixels
// obs - pointer to resultant observation vectors
// dctSize - size of the block for which DCT is calculated
// obsSize - size of top-left block of DCT coeffs matrix, which is treated
// as observation. Each observation vector consists of
// obsSize.width * obsSize.height floats.
// The following conditions should be satisfied:
// 0 < objSize.width <= dctSize.width,
// 0 < objSize.height <= dctSize.height.
// delta - dctBlocks are overlapped and this parameter specifies horizontal
// and vertical shift.
// Returns:
// CV_NO_ERR or error code
// Notes:
// The algorithm is following:
// 1. First, number of observation vectors per row and per column are calculated:
//
// Nx = floor((roi.width - dctSize.width + delta.width)/delta.width);
// Ny = floor((roi.height - dctSize.height + delta.height)/delta.height);
//
// So, total number of observation vectors is Nx*Ny, and total size of
// array obs must be >= Nx*Ny*obsSize.width*obsSize.height*sizeof(float).
// 2. Observation vectors are calculated in the following loop
// ( actual implementation may be different ), where
// I[x1:x2,y1:y2] means block of pixels from source image with
// x1 <= x < x2, y1 <= y < y2,
// D[x1:x2,y1:y2] means sub matrix of DCT matrix D.
// O[x,y] means observation vector that corresponds to position
// (x*delta.width,y*delta.height) in the source image
// ( all indices are counted from 0 ).
//
// for( y = 0; y < Ny; y++ )
// {
// for( x = 0; x < Nx; x++ )
// {
// D = DCT(I[x*delta.width : x*delta.width + dctSize.width,
// y*delta.height : y*delta.height + dctSize.height]);
// O[x,y] = D[0:obsSize.width, 0:obsSize.height];
// }
// }
//F*/
/*comment out the following line to make DCT be calculated in floating-point arithmetics*/
//#define _CV_INT_DCT
/* for integer DCT only */
#define DCT_SCALE 15
#ifdef _CV_INT_DCT
typedef int work_t;
#define DESCALE CV_DESCALE
#define SCALE(x) CV_FLT_TO_FIX((x),DCT_SCALE)
#else
typedef float work_t;
#define DESCALE(x,n) (float)(x)
#define SCALE(x) (float)(x)
#endif
/* calculate dct transform matrix */
static void icvCalcDCTMatrix( work_t * cfs, int n );
#define MAX_DCT_SIZE 32
static CvStatus CV_STDCALL
icvImgToObs_DCT_8u32f_C1R( uchar * img, int imgStep, CvSize roi,
float *obs, CvSize dctSize,
CvSize obsSize, CvSize delta )
{
/* dct transform matrices: horizontal and vertical */
work_t tab_x[MAX_DCT_SIZE * MAX_DCT_SIZE / 2 + 2];
work_t tab_y[MAX_DCT_SIZE * MAX_DCT_SIZE / 2 + 2];
/* temporary buffers for dct */
work_t temp0[MAX_DCT_SIZE * 4];
work_t temp1[MAX_DCT_SIZE * 4];
work_t *buffer = 0;
work_t *buf_limit;
double s;
int y;
int Nx, Ny;
int n1 = dctSize.height, m1 = n1 / 2;
int n2 = dctSize.width, m2 = n2 / 2;
if( !img || !obs )
return CV_NULLPTR_ERR;
if( roi.width <= 0 || roi.height <= 0 )
return CV_BADSIZE_ERR;
if( delta.width <= 0 || delta.height <= 0 )
return CV_BADRANGE_ERR;
if( obsSize.width <= 0 || dctSize.width < obsSize.width ||
obsSize.height <= 0 || dctSize.height < obsSize.height )
return CV_BADRANGE_ERR;
if( dctSize.width > MAX_DCT_SIZE || dctSize.height > MAX_DCT_SIZE )
return CV_BADRANGE_ERR;
Nx = (roi.width - dctSize.width + delta.width) / delta.width;
Ny = (roi.height - dctSize.height + delta.height) / delta.height;
if( Nx <= 0 || Ny <= 0 )
return CV_BADRANGE_ERR;
buffer = (work_t *)cvAlloc( roi.width * obsSize.height * sizeof( buffer[0] ));
if( !buffer )
return CV_OUTOFMEM_ERR;
icvCalcDCTMatrix( tab_x, dctSize.width );
icvCalcDCTMatrix( tab_y, dctSize.height );
buf_limit = buffer + obsSize.height * roi.width;
for( y = 0; y < Ny; y++, img += delta.height * imgStep )
{
int x, i, j, k;
work_t k0 = 0;
/* do transfroms for each column. Calc only first obsSize.height DCT coefficients */
for( x = 0; x < roi.width; x++ )
{
float is = 0;
work_t *buf = buffer + x;
work_t *tab = tab_y + 2;
if( n1 & 1 )
{
is = img[x + m1 * imgStep];
k0 = ((work_t) is) * tab[-1];
}
/* first coefficient */
for( j = 0; j < m1; j++ )
{
float t0 = img[x + j * imgStep];
float t1 = img[x + (n1 - 1 - j) * imgStep];
float t2 = t0 + t1;
t0 -= t1;
temp0[j] = (work_t) t2;
is += t2;
temp1[j] = (work_t) t0;
}
buf[0] = DESCALE( is * tab[-2], PASS1_SHIFT );
if( (buf += roi.width) >= buf_limit )
continue;
/* other coefficients */
for( ;; )
{
s = 0;
for( k = 0; k < m1; k++ )
s += temp1[k] * tab[k];
buf[0] = DESCALE( s, PASS1_SHIFT );
if( (buf += roi.width) >= buf_limit )
break;
tab += m1;
s = 0;
if( n1 & 1 )
{
k0 = -k0;
s = k0;
}
for( k = 0; k < m1; k++ )
s += temp0[k] * tab[k];
buf[0] = DESCALE( s, PASS1_SHIFT );
tab += m1;
if( (buf += roi.width) >= buf_limit )
break;
}
}
k0 = 0;
/* do transforms for rows. */
for( x = 0; x + dctSize.width <= roi.width; x += delta.width )
{
for( i = 0; i < obsSize.height; i++ )
{
work_t *buf = buffer + x + roi.width * i;
work_t *tab = tab_x + 2;
float *obs_limit = obs + obsSize.width;
s = 0;
if( n2 & 1 )
{
s = buf[m2];
k0 = (work_t) (s * tab[-1]);
}
/* first coefficient */
for( j = 0; j < m2; j++ )
{
work_t t0 = buf[j];
work_t t1 = buf[n2 - 1 - j];
work_t t2 = t0 + t1;
t0 -= t1;
temp0[j] = (work_t) t2;
s += t2;
temp1[j] = (work_t) t0;
}
*obs++ = (float) DESCALE( s * tab[-2], PASS2_SHIFT );
if( obs == obs_limit )
continue;
/* other coefficients */
for( ;; )
{
s = 0;
for( k = 0; k < m2; k++ )
s += temp1[k] * tab[k];
obs[0] = (float) DESCALE( s, PASS2_SHIFT );
if( ++obs == obs_limit )
break;
tab += m2;
s = 0;
if( n2 & 1 )
{
k0 = -k0;
s = k0;
}
for( k = 0; k < m2; k++ )
s += temp0[k] * tab[k];
obs[0] = (float) DESCALE( s, PASS2_SHIFT );
tab += m2;
if( ++obs == obs_limit )
break;
}
}
}
}
cvFree( &buffer );
return CV_NO_ERR;
}
static CvStatus CV_STDCALL
icvImgToObs_DCT_32f_C1R( float * img, int imgStep, CvSize roi,
float *obs, CvSize dctSize,
CvSize obsSize, CvSize delta )
{
/* dct transform matrices: horizontal and vertical */
work_t tab_x[MAX_DCT_SIZE * MAX_DCT_SIZE / 2 + 2];
work_t tab_y[MAX_DCT_SIZE * MAX_DCT_SIZE / 2 + 2];
/* temporary buffers for dct */
work_t temp0[MAX_DCT_SIZE * 4];
work_t temp1[MAX_DCT_SIZE * 4];
work_t *buffer = 0;
work_t *buf_limit;
double s;
int y;
int Nx, Ny;
int n1 = dctSize.height, m1 = n1 / 2;
int n2 = dctSize.width, m2 = n2 / 2;
if( !img || !obs )
return CV_NULLPTR_ERR;
if( roi.width <= 0 || roi.height <= 0 )
return CV_BADSIZE_ERR;
if( delta.width <= 0 || delta.height <= 0 )
return CV_BADRANGE_ERR;
if( obsSize.width <= 0 || dctSize.width < obsSize.width ||
obsSize.height <= 0 || dctSize.height < obsSize.height )
return CV_BADRANGE_ERR;
if( dctSize.width > MAX_DCT_SIZE || dctSize.height > MAX_DCT_SIZE )
return CV_BADRANGE_ERR;
Nx = (roi.width - dctSize.width + delta.width) / delta.width;
Ny = (roi.height - dctSize.height + delta.height) / delta.height;
if( Nx <= 0 || Ny <= 0 )
return CV_BADRANGE_ERR;
buffer = (work_t *)cvAlloc( roi.width * obsSize.height * sizeof( buffer[0] ));
if( !buffer )
return CV_OUTOFMEM_ERR;
icvCalcDCTMatrix( tab_x, dctSize.width );
icvCalcDCTMatrix( tab_y, dctSize.height );
buf_limit = buffer + obsSize.height * roi.width;
imgStep /= sizeof(img[0]);
for( y = 0; y < Ny; y++, img += delta.height * imgStep )
{
int x, i, j, k;
work_t k0 = 0;
/* do transfroms for each column. Calc only first obsSize.height DCT coefficients */
for( x = 0; x < roi.width; x++ )
{
float is = 0;
work_t *buf = buffer + x;
work_t *tab = tab_y + 2;
if( n1 & 1 )
{
is = img[x + m1 * imgStep];
k0 = ((work_t) is) * tab[-1];
}
/* first coefficient */
for( j = 0; j < m1; j++ )
{
float t0 = img[x + j * imgStep];
float t1 = img[x + (n1 - 1 - j) * imgStep];
float t2 = t0 + t1;
t0 -= t1;
temp0[j] = (work_t) t2;
is += t2;
temp1[j] = (work_t) t0;
}
buf[0] = DESCALE( is * tab[-2], PASS1_SHIFT );
if( (buf += roi.width) >= buf_limit )
continue;
/* other coefficients */
for( ;; )
{
s = 0;
for( k = 0; k < m1; k++ )
s += temp1[k] * tab[k];
buf[0] = DESCALE( s, PASS1_SHIFT );
if( (buf += roi.width) >= buf_limit )
break;
tab += m1;
s = 0;
if( n1 & 1 )
{
k0 = -k0;
s = k0;
}
for( k = 0; k < m1; k++ )
s += temp0[k] * tab[k];
buf[0] = DESCALE( s, PASS1_SHIFT );
tab += m1;
if( (buf += roi.width) >= buf_limit )
break;
}
}
k0 = 0;
/* do transforms for rows. */
for( x = 0; x + dctSize.width <= roi.width; x += delta.width )
{
for( i = 0; i < obsSize.height; i++ )
{
work_t *buf = buffer + x + roi.width * i;
work_t *tab = tab_x + 2;
float *obs_limit = obs + obsSize.width;
s = 0;
if( n2 & 1 )
{
s = buf[m2];
k0 = (work_t) (s * tab[-1]);
}
/* first coefficient */
for( j = 0; j < m2; j++ )
{
work_t t0 = buf[j];
work_t t1 = buf[n2 - 1 - j];
work_t t2 = t0 + t1;
t0 -= t1;
temp0[j] = (work_t) t2;
s += t2;
temp1[j] = (work_t) t0;
}
*obs++ = (float) DESCALE( s * tab[-2], PASS2_SHIFT );
if( obs == obs_limit )
continue;
/* other coefficients */
for( ;; )
{
s = 0;
for( k = 0; k < m2; k++ )
s += temp1[k] * tab[k];
obs[0] = (float) DESCALE( s, PASS2_SHIFT );
if( ++obs == obs_limit )
break;
tab += m2;
s = 0;
if( n2 & 1 )
{
k0 = -k0;
s = k0;
}
for( k = 0; k < m2; k++ )
s += temp0[k] * tab[k];
obs[0] = (float) DESCALE( s, PASS2_SHIFT );
tab += m2;
if( ++obs == obs_limit )
break;
}
}
}
}
cvFree( &buffer );
return CV_NO_ERR;
}
static void
icvCalcDCTMatrix( work_t * cfs, int n )
{
static const double sqrt2 = 1.4142135623730950488016887242097;
static const double pi = 3.1415926535897932384626433832795;
static const double sincos[16 * 2] = {
1.00000000000000000, 0.00000000000000006,
0.70710678118654746, 0.70710678118654757,
0.49999999999999994, 0.86602540378443871,
0.38268343236508978, 0.92387953251128674,
0.30901699437494740, 0.95105651629515353,
0.25881904510252074, 0.96592582628906831,
0.22252093395631439, 0.97492791218182362,
0.19509032201612825, 0.98078528040323043,
0.17364817766693033, 0.98480775301220802,
0.15643446504023087, 0.98768834059513777,
0.14231483827328514, 0.98982144188093268,
0.13052619222005157, 0.99144486137381038,
0.12053668025532305, 0.99270887409805397,
0.11196447610330786, 0.99371220989324260,
0.10452846326765346, 0.99452189536827329,
0.09801714032956060, 0.99518472667219693,
};
#define ROTATE( c, s, dc, ds ) \
{ \
t = c*dc - s*ds; \
s = c*ds + s*dc; \
c = t; \
}
#define WRITE2( j, a, b ) \
{ \
cfs[j] = SCALE(a); \
cfs2[j] = SCALE(b); \
}
double t, scale = 1. / sqrt( (double)n );
int i, j, m = n / 2;
cfs[0] = SCALE( scale );
scale *= sqrt2;
cfs[1] = SCALE( scale );
cfs += 2 - m;
if( n > 1 )
{
double a0, b0;
double da0, db0;
work_t *cfs2 = cfs + m * n;
if( n <= 16 )
{
da0 = a0 = sincos[2 * n - 1];
db0 = b0 = sincos[2 * n - 2];
}
else
{
t = pi / (2 * n);
da0 = a0 = cos( t );
db0 = b0 = sin( t );
}
/* other rows */
for( i = 1; i <= m; i++ )
{
double a = a0 * scale;
double b = b0 * scale;
double da = a0 * a0 - b0 * b0;
double db = a0 * b0 + a0 * b0;
cfs += m;
cfs2 -= m;
for( j = 0; j < m; j += 2 )
{
WRITE2( j, a, b );
ROTATE( a, b, da, db );
if( j + 1 < m )
{
WRITE2( j + 1, a, -b );
ROTATE( a, b, da, db );
}
}
ROTATE( a0, b0, da0, db0 );
}
}
#undef ROTATE
#undef WRITE2
}
CV_IMPL void
cvImgToObs_DCT( const void* arr, float *obs, CvSize dctSize,
CvSize obsSize, CvSize delta )
{
CV_FUNCNAME( "cvImgToObs_DCT" );
__BEGIN__;
CvMat stub, *mat = (CvMat*)arr;
CV_CALL( mat = cvGetMat( arr, &stub ));
switch( CV_MAT_TYPE( mat->type ))
{
case CV_8UC1:
IPPI_CALL( icvImgToObs_DCT_8u32f_C1R( mat->data.ptr, mat->step,
cvGetMatSize(mat), obs,
dctSize, obsSize, delta ));
break;
case CV_32FC1:
IPPI_CALL( icvImgToObs_DCT_32f_C1R( mat->data.fl, mat->step,
cvGetMatSize(mat), obs,
dctSize, obsSize, delta ));
break;
default:
CV_ERROR( CV_StsUnsupportedFormat, "" );
}
__END__;
}
/* End of file. */

View File

@@ -0,0 +1,310 @@
/*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*/
/* ////////////////////////////////////////////////////////////////////
//
// C++ classes for image and matrices
//
// */
#include "precomp.hpp"
#include "opencv2/highgui/highgui_c.h"
/////////////////////////////// CvImage implementation //////////////////////////////////
static bool
icvIsXmlOrYaml( const char* filename )
{
const char* suffix = strrchr( filename, '.' );
return suffix &&
(strcmp( suffix, ".xml" ) == 0 ||
strcmp( suffix, ".Xml" ) == 0 ||
strcmp( suffix, ".XML" ) == 0 ||
strcmp( suffix, ".yml" ) == 0 ||
strcmp( suffix, ".Yml" ) == 0 ||
strcmp( suffix, ".YML" ) == 0 ||
strcmp( suffix, ".yaml" ) == 0 ||
strcmp( suffix, ".Yaml" ) == 0 ||
strcmp( suffix, ".YAML" ) == 0);
}
static IplImage*
icvRetrieveImage( void* obj )
{
IplImage* img = 0;
if( CV_IS_IMAGE(obj) )
img = (IplImage*)obj;
else if( CV_IS_MAT(obj) )
{
CvMat* m = (CvMat*)obj;
img = cvCreateImageHeader( cvSize(m->cols,m->rows),
CV_MAT_DEPTH(m->type), CV_MAT_CN(m->type) );
cvSetData( img, m->data.ptr, m->step );
img->imageDataOrigin = (char*)m->refcount;
m->data.ptr = 0; m->step = 0;
cvReleaseMat( &m );
}
else if( obj )
{
cvRelease( &obj );
CV_Error( CV_StsUnsupportedFormat, "The object is neither an image, nor a matrix" );
}
return img;
}
bool CvImage::load( const char* filename, const char* imgname, int color )
{
IplImage* img = 0;
if( icvIsXmlOrYaml(filename) )
{
img = icvRetrieveImage(cvLoad(filename,0,imgname));
if( (img->nChannels > 1) != (color == 0) )
CV_Error( CV_StsNotImplemented,
"RGB<->Grayscale conversion is not implemented for images stored in XML/YAML" );
/*{
IplImage* temp_img = 0;
temp_img = cvCreateImage( cvGetSize(img), img->depth, color > 0 ? 3 : 1 ));
cvCvtColor( img, temp_img, color > 0 ? CV_GRAY2BGR : CV_BGR2GRAY );
cvReleaseImage( &img );
img = temp_img;
}*/
}
else
img = cvLoadImage( filename, color );
attach( img );
return img != 0;
}
bool CvImage::read( CvFileStorage* fs, const char* mapname, const char* imgname )
{
void* obj = 0;
IplImage* img = 0;
if( mapname )
{
CvFileNode* mapnode = cvGetFileNodeByName( fs, 0, mapname );
if( !mapnode )
obj = cvReadByName( fs, mapnode, imgname );
}
else
obj = cvReadByName( fs, 0, imgname );
img = icvRetrieveImage(obj);
attach( img );
return img != 0;
}
bool CvImage::read( CvFileStorage* fs, const char* seqname, int idx )
{
void* obj = 0;
IplImage* img = 0;
CvFileNode* seqnode = seqname ?
cvGetFileNodeByName( fs, 0, seqname ) : cvGetRootFileNode(fs,0);
if( seqnode && CV_NODE_IS_SEQ(seqnode->tag) )
obj = cvRead( fs, (CvFileNode*)cvGetSeqElem( seqnode->data.seq, idx ));
img = icvRetrieveImage(obj);
attach( img );
return img != 0;
}
void CvImage::save( const char* filename, const char* imgname, const int* params )
{
if( !image )
return;
if( icvIsXmlOrYaml( filename ) )
cvSave( filename, image, imgname );
else
cvSaveImage( filename, image, params );
}
void CvImage::write( CvFileStorage* fs, const char* imgname )
{
if( image )
cvWrite( fs, imgname, image );
}
void CvImage::show( const char* window_name )
{
if( image )
cvShowImage( window_name, image );
}
/////////////////////////////// CvMatrix implementation //////////////////////////////////
CvMatrix::CvMatrix( int rows, int cols, int type, CvMemStorage* storage, bool alloc_data )
{
if( storage )
{
matrix = (CvMat*)cvMemStorageAlloc( storage, sizeof(*matrix) );
cvInitMatHeader( matrix, rows, cols, type, alloc_data ?
cvMemStorageAlloc( storage, rows*cols*CV_ELEM_SIZE(type) ) : 0 );
}
else
matrix = 0;
}
static CvMat*
icvRetrieveMatrix( void* obj )
{
CvMat* m = 0;
if( CV_IS_MAT(obj) )
m = (CvMat*)obj;
else if( CV_IS_IMAGE(obj) )
{
IplImage* img = (IplImage*)obj;
CvMat hdr, *src = cvGetMat( img, &hdr );
m = cvCreateMat( src->rows, src->cols, src->type );
cvCopy( src, m );
cvReleaseImage( &img );
}
else if( obj )
{
cvRelease( &obj );
CV_Error( CV_StsUnsupportedFormat, "The object is neither an image, nor a matrix" );
}
return m;
}
bool CvMatrix::load( const char* filename, const char* matname, int color )
{
CvMat* m = 0;
if( icvIsXmlOrYaml(filename) )
{
m = icvRetrieveMatrix(cvLoad(filename,0,matname));
if( (CV_MAT_CN(m->type) > 1) != (color == 0) )
CV_Error( CV_StsNotImplemented,
"RGB<->Grayscale conversion is not implemented for matrices stored in XML/YAML" );
/*{
CvMat* temp_mat;
temp_mat = cvCreateMat( m->rows, m->cols,
CV_MAKETYPE(CV_MAT_DEPTH(m->type), color > 0 ? 3 : 1 )));
cvCvtColor( m, temp_mat, color > 0 ? CV_GRAY2BGR : CV_BGR2GRAY );
cvReleaseMat( &m );
m = temp_mat;
}*/
}
else
m = cvLoadImageM( filename, color );
set( m, false );
return m != 0;
}
bool CvMatrix::read( CvFileStorage* fs, const char* mapname, const char* matname )
{
void* obj = 0;
CvMat* m = 0;
if( mapname )
{
CvFileNode* mapnode = cvGetFileNodeByName( fs, 0, mapname );
if( !mapnode )
obj = cvReadByName( fs, mapnode, matname );
}
else
obj = cvReadByName( fs, 0, matname );
m = icvRetrieveMatrix(obj);
set( m, false );
return m != 0;
}
bool CvMatrix::read( CvFileStorage* fs, const char* seqname, int idx )
{
void* obj = 0;
CvMat* m = 0;
CvFileNode* seqnode = seqname ?
cvGetFileNodeByName( fs, 0, seqname ) : cvGetRootFileNode(fs,0);
if( seqnode && CV_NODE_IS_SEQ(seqnode->tag) )
obj = cvRead( fs, (CvFileNode*)cvGetSeqElem( seqnode->data.seq, idx ));
m = icvRetrieveMatrix(obj);
set( m, false );
return m != 0;
}
void CvMatrix::save( const char* filename, const char* matname, const int* params )
{
if( !matrix )
return;
if( icvIsXmlOrYaml( filename ) )
cvSave( filename, matrix, matname );
else
cvSaveImage( filename, matrix, params );
}
void CvMatrix::write( CvFileStorage* fs, const char* matname )
{
if( matrix )
cvWrite( fs, matname, matrix );
}
void CvMatrix::show( const char* window_name )
{
if( matrix )
cvShowImage( window_name, matrix );
}
/* End of file. */

724
modules/legacy/src/lcm.cpp Normal file
View File

@@ -0,0 +1,724 @@
/*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*/
/* Hybrid linear-contour model reconstruction */
#include "precomp.hpp"
#define CV_IMPL CV_EXTERN_C
const float LCM_CONST_ZERO = 1e-6f;
/****************************************************************************************\
* Auxiliary struct definitions *
\****************************************************************************************/
typedef struct CvLCM
{
CvGraph* Graph;
CvVoronoiDiagram2D* VoronoiDiagram;
CvMemStorage* ContourStorage;
CvMemStorage* EdgeStorage;
float maxWidth;
} CvLCM;
typedef struct CvLCMComplexNodeData
{
CvVoronoiNode2D edge_node;
CvPoint2D32f site_first_pt;
CvPoint2D32f site_last_pt;
CvVoronoiSite2D* site_first;
CvVoronoiSite2D* site_last;
CvVoronoiEdge2D* edge;
} CvLCMComplexNodeData;
typedef struct CvLCMData
{
CvVoronoiNode2D* pnode;
CvVoronoiSite2D* psite;
CvVoronoiEdge2D* pedge;
} CvLCMData;
/****************************************************************************************\
* Function definitions *
\****************************************************************************************/
#define _CV_READ_SEQ_ELEM( elem, reader, type ) \
{ \
assert( (reader).seq->elem_size == sizeof(*elem)); \
elem = (type)(reader).ptr; \
CV_NEXT_SEQ_ELEM( sizeof(*elem), reader ) \
}
#define _CV_IS_SITE_REFLEX( SITE ) ((SITE) ->node[0] == (SITE) ->node[1])
#define _CV_IS_EDGE_REFLEX( EDGE ) (( (EDGE)->site[0]->node[0] == (EDGE)->site[0]->node[0] ) || \
( (EDGE)->site[1]->node[0] == (EDGE)->site[1]->node[0] ) )
#define _CV_INITIALIZE_CVLCMDATA(STRUCT,SITE,EDGE,NODE)\
{ (STRUCT)->psite = SITE ; (STRUCT)->pedge = EDGE; (STRUCT)->pnode = NODE;}
/*F///////////////////////////////////////////////////////////////////////////////////////
// Author: Andrey Sobolev
// Name: _cvConstructLCM
// Purpose: Function constructs hybrid model
// Context:
// Parameters:
// LCM : in&out.
// Returns: 1, if hybrid model was succesfully constructed
// 0, if some error occures
//F*/
CV_IMPL
int _cvConstructLCM(CvLCM* LCM);
/*F///////////////////////////////////////////////////////////////////////////////////////
// Author: Andrey Sobolev
// Name: _cvConstructLCMComplexNode
// Purpose: Function constructs Complex Node (node, which consists of
// two points and more) of hybrid model
// Context:
// Parameters:
// pLCM : in&out.
// pLCMEdge: in, input edge of hybrid model
// pLCMInputData: in, input parameters
// Returns: pointer to constructed node
//F*/
CV_IMPL
CvLCMNode* _cvConstructLCMComplexNode(CvLCM* pLCM,
CvLCMEdge* pLCMEdge,
CvLCMData* pLCMInputData);
/*F///////////////////////////////////////////////////////////////////////////////////////
// Author: Andrey Sobolev
// Name: _cvConstructLCMSimpleNode
// Purpose: Function constructs Simple Node (node, which consists of
// one point) of hybrid model
// Context:
// Parameters:
// pLCM : in&out.
// pLCMEdge: in, input edge of hybrid model
// pLCMInputData: in, input parameters
// Returns: pointer to constructed node
//F*/
CV_IMPL
CvLCMNode* _cvConstructLCMSimpleNode(CvLCM* pLCM,
CvLCMEdge* pLCMEdge,
CvLCMData* pLCMInputData);
/*F///////////////////////////////////////////////////////////////////////////////////////
// Author: Andrey Sobolev
// Name: _cvConstructLCMSimpleNode
// Purpose: Function constructs Edge of hybrid model
// Context:
// Parameters:
// pLCM : in&out.
// pLCMInputData: in, input parameters
// Returns: pointer to constructed edge
//F*/
CV_IMPL
CvLCMEdge* _cvConstructLCMEdge(CvLCM* pLCM,
CvLCMData* pLCMInputData);
/*F///////////////////////////////////////////////////////////////////////////////////////
// Author: Andrey Sobolev
// Name: _cvTreatExeptionalCase
// Purpose: Function treats triangles and regular polygons
// Context:
// Parameters:
// pLCM : in, information about graph
// pLCMInputData: in, input parameters
// Returns: pointer to graph node
//F*/
CV_IMPL
CvLCMNode* _cvTreatExeptionalCase(CvLCM* pLCM,
CvLCMData* pLCMInputData);
/*F///////////////////////////////////////////////////////////////////////////////////////
// Author: Andrey Sobolev
// Name: _cvNodeMultyplicity
// Purpose: Function seeks all non-boundary edges incident to
// given node and correspondent incident sites
// Context:
// Parameters:
// pEdge : in, original edge
// pNode : in, given node
// LinkedEdges : out, matrix of incident edges
// LinkedSites : out, matrix of incident sites
// pSite: in, original site (pNode must be the begin point of pEdge
// for this pSite, this property hold out far all edges)
// Returns: number of incident edges (must be less than 10)
//F*/
CV_IMPL
int _cvNodeMultyplicity(CvVoronoiSite2D* pSite,
CvVoronoiEdge2D* pEdge,
CvVoronoiNode2D* pNode,
CvVoronoiEdge2D** LinkedEdges,
CvVoronoiSite2D** LinkedSites);
/*F///////////////////////////////////////////////////////////////////////////////////////
// Author: Andrey Sobolev
// Name: _cvCreateLCMNode
// Purpose: Function create graph node
// Context:
// Parameters:
// pLCM : in, information about graph
// Returns: pointer to graph node
//F*/
CV_IMPL
CvLCMNode* _cvCreateLCMNode(CvLCM* pLCM);
/*F///////////////////////////////////////////////////////////////////////////////////////
// Author: Andrey Sobolev
// Name: _cvCreateLCMEdge
// Purpose: Function create graph edge
// Context:
// Parameters:
// pLCM : in, information about graph
// Returns: pointer to graph edge
//F*/
CV_IMPL
CvLCMEdge* _cvCreateLCMEdge(CvLCM* pLCM);
/*F///////////////////////////////////////////////////////////////////////////////////////
// Author: Andrey Sobolev
// Name: _cvCreateLCMNode
// Purpose: Function establishs the connection between node and ege
// Context:
// Parameters:
// LCMNode : in, graph node
// LCMEdge : in, graph edge
// LCMEdge_prev : in&out, previous edge, connected with given node
// index: in,
// i : =0, if node is initial for edge
// =1, if node is terminal for edge
// Returns:
//F*/
CV_IMPL
void _cvAttachLCMEdgeToLCMNode(CvLCMNode* LCMNode,
CvLCMEdge* LCMEdge,
CvLCMEdge* &LCMEdge_prev,
int index,
int i);
/*F///////////////////////////////////////////////////////////////////////////////////////
// Author: Andrey Sobolev
// Name: _cvProjectionPointToSegment
// Purpose: Function computes the ortogonal projection of PointO to
// to segment[PointA, PointB]
// Context:
// Parameters:
// PointO, PointA,PointB: in, given points
// PrPoint : out, projection
// dist : distance from PointO to PrPoint
// Returns:
//F*/
CV_IMPL
void _cvProjectionPointToSegment(CvPoint2D32f* PointO,
CvPoint2D32f* PointA,
CvPoint2D32f* PointB,
CvPoint2D32f* PrPoint,
float* dist);
/*F///////////////////////////////////////////////////////////////////////////////////////
// Author: Andrey Sobolev
// Name: _cvPrepareData
// Purpose: Function fills up the struct CvLCMComplexNodeData
// Context:
// Parameters:
// pLCMData : in
// pLCMCCNData : out
// Returns:
//F*/
CV_IMPL
void _cvPrepareData(CvLCMComplexNodeData* pLCMCCNData,
CvLCMData* pLCMData);
/****************************************************************************************\
* Function realization *
\****************************************************************************************/
CV_IMPL CvGraph* cvLinearContorModelFromVoronoiDiagram(CvVoronoiDiagram2D* VoronoiDiagram,
float maxWidth)
{
CvMemStorage* LCMstorage;
CvSet* SiteSet;
CvLCM LCM = {NULL, VoronoiDiagram,NULL,NULL,maxWidth};
CV_FUNCNAME( "cvLinearContorModelFromVoronoiDiagram" );
__BEGIN__;
if( !VoronoiDiagram )
CV_ERROR( CV_StsBadArg,"Voronoi Diagram is not defined" );
if( maxWidth < 0 )
CV_ERROR( CV_StsBadArg,"Treshold parameter must be non negative" );
for(SiteSet = VoronoiDiagram->sites;
SiteSet != NULL;
SiteSet = (CvSet*)SiteSet->h_next)
{
if(SiteSet->v_next)
CV_ERROR( CV_StsBadArg,"Can't operate with multiconnected domains" );
if(SiteSet->total > 70000)
CV_ERROR( CV_StsBadArg,"Can't operate with large domains" );
}
LCMstorage = cvCreateMemStorage(0);
LCM.EdgeStorage = cvCreateChildMemStorage(LCMstorage);
LCM.ContourStorage = cvCreateChildMemStorage(LCMstorage);
LCM.Graph = cvCreateGraph(CV_SEQ_KIND_GRAPH|CV_GRAPH_FLAG_ORIENTED,
sizeof(CvGraph),
sizeof(CvLCMNode),
sizeof(CvLCMEdge),
LCMstorage);
if(!_cvConstructLCM(&LCM))
cvReleaseLinearContorModelStorage(&LCM.Graph);
__END__;
return LCM.Graph;
}//end of cvLinearContorModelFromVoronoiDiagram
CV_IMPL int cvReleaseLinearContorModelStorage(CvGraph** Graph)
{
CvSeq* LCMNodeSeq, *LCMEdgeSeq;
CvLCMNode* pLCMNode;
CvLCMEdge* pLCMEdge;
/*CV_FUNCNAME( "cvReleaseLinearContorModelStorage" );*/
__BEGIN__;
if(!Graph || !(*Graph))
return 0;
LCMNodeSeq = (CvSeq*)(*Graph);
LCMEdgeSeq = (CvSeq*)(*Graph)->edges;
if(LCMNodeSeq->total > 0)
{
pLCMNode = (CvLCMNode*)cvGetSeqElem(LCMNodeSeq,0);
if(pLCMNode->contour->storage)
cvReleaseMemStorage(&pLCMNode->contour->storage);
}
if(LCMEdgeSeq->total > 0)
{
pLCMEdge = (CvLCMEdge*)cvGetSeqElem(LCMEdgeSeq,0);
if(pLCMEdge->chain->storage)
cvReleaseMemStorage(&pLCMEdge->chain->storage);
}
if((*Graph)->storage)
cvReleaseMemStorage(&(*Graph)->storage);
*Graph = NULL;
__END__;
return 1;
}//end of cvReleaseLinearContorModelStorage
int _cvConstructLCM(CvLCM* LCM)
{
CvVoronoiSite2D* pSite = 0;
CvVoronoiEdge2D* pEdge = 0, *pEdge1;
CvVoronoiNode2D* pNode, *pNode1;
CvVoronoiEdge2D* LinkedEdges[10];
CvVoronoiSite2D* LinkedSites[10];
CvSeqReader reader;
CvLCMData LCMdata;
int i;
for(CvSet* SiteSet = LCM->VoronoiDiagram->sites;
SiteSet != NULL;
SiteSet = (CvSet*)SiteSet->h_next)
{
cvStartReadSeq((CvSeq*)SiteSet, &reader);
for(i = 0; i < SiteSet->total; i++)
{
_CV_READ_SEQ_ELEM(pSite,reader,CvVoronoiSite2D*);
if(pSite->node[0] == pSite->node[1])
continue;
pEdge = CV_LAST_VORONOIEDGE2D(pSite);
pNode = CV_VORONOIEDGE2D_BEGINNODE(pEdge,pSite);
if(pNode->radius > LCM->maxWidth)
goto PREPARECOMPLEXNODE;
pEdge1 = CV_PREV_VORONOIEDGE2D(pEdge,pSite);
pNode1 = CV_VORONOIEDGE2D_BEGINNODE(pEdge1,pSite);
if(pNode1->radius > LCM->maxWidth)
goto PREPARECOMPLEXNODE;
if(pNode1->radius == 0)
continue;
if(_cvNodeMultyplicity(pSite, pEdge,pNode,LinkedEdges,LinkedSites) == 1)
goto PREPARESIMPLENODE;
}
// treate triangle or regular polygon
_CV_INITIALIZE_CVLCMDATA(&LCMdata,pSite,pEdge,CV_VORONOIEDGE2D_ENDNODE(pEdge,pSite));
if(!_cvTreatExeptionalCase(LCM,&LCMdata))
return 0;
continue;
PREPARECOMPLEXNODE:
_CV_INITIALIZE_CVLCMDATA(&LCMdata,pSite,pEdge,CV_VORONOIEDGE2D_ENDNODE(pEdge,pSite));
if(!_cvConstructLCMComplexNode(LCM,NULL,&LCMdata))
return 0;
continue;
PREPARESIMPLENODE:
_CV_INITIALIZE_CVLCMDATA(&LCMdata,pSite,pEdge,CV_VORONOIEDGE2D_ENDNODE(pEdge,pSite));
if(!_cvConstructLCMSimpleNode(LCM,NULL,&LCMdata))
return 0;
continue;
}
return 1;
}//end of _cvConstructLCM
CvLCMNode* _cvConstructLCMComplexNode(CvLCM* pLCM,
CvLCMEdge* pLCMEdge,
CvLCMData* pLCMInputData)
{
CvLCMNode* pLCMNode;
CvLCMEdge* pLCMEdge_prev = NULL;
CvSeqWriter writer;
CvVoronoiSite2D* pSite, *pSite_first, *pSite_last;
CvVoronoiEdge2D* pEdge, *pEdge_stop;
CvVoronoiNode2D* pNode0, *pNode1;
CvLCMData LCMOutputData;
CvLCMComplexNodeData LCMCCNData;
int index = 0;
_cvPrepareData(&LCMCCNData,pLCMInputData);
pLCMNode = _cvCreateLCMNode(pLCM);
_cvAttachLCMEdgeToLCMNode(pLCMNode,pLCMEdge,pLCMEdge_prev,1,1);
cvStartAppendToSeq((CvSeq*)pLCMNode->contour,&writer);
CV_WRITE_SEQ_ELEM(LCMCCNData.site_last_pt, writer);
index++;
if(pLCMEdge)
{
CV_WRITE_SEQ_ELEM(LCMCCNData.edge_node.pt, writer );
CV_WRITE_SEQ_ELEM(LCMCCNData.site_first_pt, writer );
index+=2;
}
pSite_first = LCMCCNData.site_first;
pSite_last = LCMCCNData.site_last;
pEdge = LCMCCNData.edge;
for(pSite = pSite_first;
pSite != pSite_last;
pSite = CV_NEXT_VORONOISITE2D(pSite),
pEdge = CV_PREV_VORONOIEDGE2D(CV_LAST_VORONOIEDGE2D(pSite),pSite))
{
pEdge_stop = CV_FIRST_VORONOIEDGE2D(pSite);
for(;pEdge && pEdge != pEdge_stop;
pEdge = CV_PREV_VORONOIEDGE2D(pEdge,pSite))
{
pNode0 = CV_VORONOIEDGE2D_BEGINNODE(pEdge,pSite);
pNode1 = CV_VORONOIEDGE2D_ENDNODE(pEdge,pSite);
if(pNode0->radius <= pLCM->maxWidth && pNode1->radius <= pLCM->maxWidth)
{
_CV_INITIALIZE_CVLCMDATA(&LCMOutputData,pSite,pEdge,pNode1);
_cvPrepareData(&LCMCCNData,&LCMOutputData);
CV_WRITE_SEQ_ELEM(LCMCCNData.site_first_pt, writer);
CV_WRITE_SEQ_ELEM(LCMCCNData.edge_node.pt, writer );
index+=2;
pLCMEdge = _cvConstructLCMEdge(pLCM,&LCMOutputData);
_cvAttachLCMEdgeToLCMNode(pLCMNode,pLCMEdge,pLCMEdge_prev,index - 1,0);
CV_WRITE_SEQ_ELEM(LCMCCNData.site_last_pt, writer);
index++;
pSite = CV_TWIN_VORONOISITE2D(pSite,pEdge);
pEdge_stop = CV_FIRST_VORONOIEDGE2D(pSite);
if(pSite == pSite_last)
break;
}
}
if(pSite == pSite_last)
break;
CV_WRITE_SEQ_ELEM(pSite->node[1]->pt, writer);
index++;
}
if(pLCMEdge_prev)
pLCMEdge_prev->next[(pLCMEdge_prev == (CvLCMEdge*)pLCMNode->first)] = pLCMNode->first;
cvEndWriteSeq(&writer);
return pLCMNode;
}//end of _cvConstructLCMComplexNode
CvLCMNode* _cvConstructLCMSimpleNode(CvLCM* pLCM,
CvLCMEdge* pLCMEdge,
CvLCMData* pLCMInputData)
{
CvVoronoiEdge2D* pEdge = pLCMInputData->pedge;
CvVoronoiSite2D* pSite = pLCMInputData->psite;
CvVoronoiNode2D* pNode = CV_VORONOIEDGE2D_BEGINNODE(pEdge,pSite);
CvVoronoiEdge2D* LinkedEdges[10];
CvVoronoiSite2D* LinkedSites[10];
int multyplicity = _cvNodeMultyplicity(pSite,pEdge,pNode,LinkedEdges,LinkedSites);
if(multyplicity == 2)
{
pLCMInputData->pedge = LinkedEdges[1];
pLCMInputData->psite = CV_TWIN_VORONOISITE2D(LinkedSites[1],LinkedEdges[1]);
return NULL;
}
CvLCMEdge* pLCMEdge_prev = NULL;
CvLCMNode* pLCMNode;
CvLCMData LCMOutputData;
pLCMNode = _cvCreateLCMNode(pLCM);
cvSeqPush((CvSeq*)pLCMNode->contour,&pNode->pt);
_cvAttachLCMEdgeToLCMNode(pLCMNode,pLCMEdge,pLCMEdge_prev,0,1);
for(int i = (int)(pLCMEdge != NULL);i < multyplicity; i++)
{
pEdge = LinkedEdges[i];
pSite = LinkedSites[i];
_CV_INITIALIZE_CVLCMDATA(&LCMOutputData,CV_TWIN_VORONOISITE2D(pSite,pEdge),pEdge,pNode);
pLCMEdge = _cvConstructLCMEdge(pLCM,&LCMOutputData);
_cvAttachLCMEdgeToLCMNode(pLCMNode,pLCMEdge,pLCMEdge_prev,0,0);
}
pLCMEdge_prev->next[(pLCMEdge_prev == (CvLCMEdge*)pLCMNode->first)] = pLCMNode->first;
return pLCMNode;
}//end of _cvConstructLCMSimpleNode
CvLCMEdge* _cvConstructLCMEdge(CvLCM* pLCM,
CvLCMData* pLCMInputData)
{
CvVoronoiEdge2D* pEdge = pLCMInputData->pedge;
CvVoronoiSite2D* pSite = pLCMInputData->psite;
float width = 0;
CvLCMData LCMData;
CvVoronoiNode2D* pNode0,*pNode1;
CvLCMEdge* pLCMEdge = _cvCreateLCMEdge(pLCM);
CvSeqWriter writer;
cvStartAppendToSeq(pLCMEdge->chain,&writer );
pNode0 = pNode1 = pLCMInputData->pnode;
CV_WRITE_SEQ_ELEM(pNode0->pt, writer);
width += pNode0->radius;
for(int counter = 0;
counter < pLCM->VoronoiDiagram->edges->total;
counter++)
{
pNode1 = CV_VORONOIEDGE2D_BEGINNODE(pEdge,pSite);
if(pNode1->radius >= pLCM->maxWidth)
goto CREATECOMPLEXNODE;
CV_WRITE_SEQ_ELEM(pNode1->pt,writer);
width += pNode1->radius;
_CV_INITIALIZE_CVLCMDATA(&LCMData,pSite,pEdge,pNode1);
if(_cvConstructLCMSimpleNode(pLCM,pLCMEdge,&LCMData))
goto LCMEDGEEXIT;
pEdge = LCMData.pedge; pSite = LCMData.psite;
pNode0 = pNode1;
}
return NULL;
CREATECOMPLEXNODE:
_CV_INITIALIZE_CVLCMDATA(&LCMData,pSite,pEdge,pNode0);
CV_WRITE_SEQ_ELEM(LCMData.pnode->pt,writer);
width += LCMData.pnode->radius;
_cvConstructLCMComplexNode(pLCM,pLCMEdge,&LCMData);
LCMEDGEEXIT:
cvEndWriteSeq(&writer);
pLCMEdge->width = width/pLCMEdge->chain->total;
return pLCMEdge;
}//end of _cvConstructLCMEdge
CvLCMNode* _cvTreatExeptionalCase(CvLCM* pLCM,
CvLCMData* pLCMInputData)
{
CvVoronoiEdge2D* pEdge = pLCMInputData->pedge;
CvVoronoiSite2D* pSite = pLCMInputData->psite;
CvVoronoiNode2D* pNode = CV_VORONOIEDGE2D_BEGINNODE(pEdge,pSite);
CvLCMNode* pLCMNode = _cvCreateLCMNode(pLCM);
cvSeqPush((CvSeq*)pLCMNode->contour,&pNode->pt);
return pLCMNode;
}//end of _cvConstructLCMEdge
CV_INLINE
CvLCMNode* _cvCreateLCMNode(CvLCM* pLCM)
{
CvLCMNode* pLCMNode;
cvSetAdd((CvSet*)pLCM->Graph, NULL, (CvSetElem**)&pLCMNode );
pLCMNode->contour = (CvContour*)cvCreateSeq(0, sizeof(CvContour),
sizeof(CvPoint2D32f),pLCM->ContourStorage);
pLCMNode->first = NULL;
return pLCMNode;
}//end of _cvCreateLCMNode
CV_INLINE
CvLCMEdge* _cvCreateLCMEdge(CvLCM* pLCM)
{
CvLCMEdge* pLCMEdge;
cvSetAdd( (CvSet*)(pLCM->Graph->edges), 0, (CvSetElem**)&pLCMEdge );
pLCMEdge->chain = cvCreateSeq(0, sizeof(CvSeq),sizeof(CvPoint2D32f),pLCM->EdgeStorage);
pLCMEdge->next[0] = pLCMEdge->next[1] = NULL;
pLCMEdge->vtx[0] = pLCMEdge->vtx[1] = NULL;
pLCMEdge->index1 = pLCMEdge->index2 = -1;
return pLCMEdge;
}//end of _cvCreateLCMEdge
CV_INLINE
void _cvAttachLCMEdgeToLCMNode(CvLCMNode* LCMNode,
CvLCMEdge* LCMEdge,
CvLCMEdge* &LCMEdge_prev,
int index,
int i)
{
if(!LCMEdge)
return;
if(i==0)
LCMEdge->index1 = index;
else
LCMEdge->index2 = index;
LCMEdge->vtx[i] = (CvGraphVtx*)LCMNode;
if(!LCMEdge_prev)
LCMNode->first = (CvGraphEdge*)LCMEdge;
else
// LCMEdge_prev->next[(LCMEdge_prev == (CvLCMEdge*)LCMNode->first)] = (CvGraphEdge*)LCMEdge;
LCMEdge_prev->next[(LCMEdge_prev->vtx[0] != (CvGraphVtx*)LCMNode)] = (CvGraphEdge*)LCMEdge;
LCMEdge->next[i] = LCMNode->first;
LCMEdge_prev = LCMEdge;
}//end of _cvAttachLCMEdgeToLCMNode
int _cvNodeMultyplicity(CvVoronoiSite2D* pSite,
CvVoronoiEdge2D* pEdge,
CvVoronoiNode2D* pNode,
CvVoronoiEdge2D** LinkedEdges,
CvVoronoiSite2D** LinkedSites)
{
if(!pNode->radius)
return -1;
assert(pNode == CV_VORONOIEDGE2D_BEGINNODE(pEdge,pSite));
int multyplicity = 0;
CvVoronoiEdge2D* pEdge_cur = pEdge;
do
{
if(pEdge_cur->node[0]->radius && pEdge_cur->node[1]->radius)
{
LinkedEdges[multyplicity] = pEdge_cur;
LinkedSites[multyplicity] = pSite;
multyplicity++;
}
pEdge_cur = CV_PREV_VORONOIEDGE2D(pEdge_cur,pSite);
pSite = CV_TWIN_VORONOISITE2D(pSite,pEdge_cur);
}while(pEdge_cur != pEdge);
return multyplicity;
}//end of _cvNodeMultyplicity
CV_INLINE
void _cvPrepareData(CvLCMComplexNodeData* pLCMCCNData,
CvLCMData* pLCMData)
{
pLCMCCNData->site_first = pLCMData->psite;
pLCMCCNData->site_last = CV_TWIN_VORONOISITE2D(pLCMData->psite,pLCMData->pedge);
if(pLCMData->pedge == CV_LAST_VORONOIEDGE2D(pLCMData->psite))
{
pLCMCCNData->edge = CV_PREV_VORONOIEDGE2D(pLCMData->pedge,pLCMData->psite);
pLCMCCNData->edge_node = *pLCMData->pnode;
pLCMCCNData->site_first_pt = pLCMData->psite->node[0]->pt;
pLCMCCNData->site_last_pt = pLCMData->psite->node[0]->pt;
}
else
{
pLCMCCNData->edge = pLCMData->pedge;
pLCMCCNData->edge_node = *pLCMData->pnode;
_cvProjectionPointToSegment(&pLCMCCNData->edge_node.pt,
&pLCMCCNData->site_first->node[0]->pt,
&pLCMCCNData->site_first->node[1]->pt,
&pLCMCCNData->site_first_pt,
NULL);
_cvProjectionPointToSegment(&pLCMCCNData->edge_node.pt,
&pLCMCCNData->site_last->node[0]->pt,
&pLCMCCNData->site_last->node[1]->pt,
&pLCMCCNData->site_last_pt,
NULL);
}
}//end of _cvPrepareData
void _cvProjectionPointToSegment(CvPoint2D32f* PointO,
CvPoint2D32f* PointA,
CvPoint2D32f* PointB,
CvPoint2D32f* PrPoint,
float* dist)
{
float scal_AO_AB, scal_AB_AB;
CvPoint2D32f VectorAB = {PointB->x - PointA->x, PointB->y - PointA->y};
scal_AB_AB = VectorAB.x*VectorAB.x + VectorAB.y*VectorAB.y;
if(scal_AB_AB < LCM_CONST_ZERO)
{
*PrPoint = *PointA;
if(dist)
*dist = (float)sqrt( (double)(PointO->x -PointA->x)*(PointO->x -PointA->x) + (PointO->y - PointA->y)*(PointO->y - PointA->y));
return;
}
CvPoint2D32f VectorAO = {PointO->x - PointA->x, PointO->y - PointA->y};
scal_AO_AB = VectorAO.x*VectorAB.x + VectorAO.y*VectorAB.y;
if(dist)
{
float vector_AO_AB = (float)fabs(VectorAO.x*VectorAB.y - VectorAO.y*VectorAB.x);
*dist = (float)(vector_AO_AB/sqrt((double)scal_AB_AB));
}
float alfa = scal_AO_AB/scal_AB_AB;
PrPoint->x = PointO->x - VectorAO.x + alfa*VectorAB.x;
PrPoint->y = PointO->y - VectorAO.y + alfa*VectorAB.y;
return;
}//end of _cvProjectionPointToSegment

4715
modules/legacy/src/lee.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,318 @@
/*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 <float.h>
#include <limits.h>
/* Valery Mosyagin */
//#define TRACKLEVMAR
typedef void (*pointer_LMJac)( const CvMat* src, CvMat* dst );
typedef void (*pointer_LMFunc)( const CvMat* src, CvMat* dst );
/* Optimization using Levenberg-Marquardt */
void cvLevenbergMarquardtOptimization(pointer_LMJac JacobianFunction,
pointer_LMFunc function,
/*pointer_Err error_function,*/
CvMat *X0,CvMat *observRes,CvMat *resultX,
int maxIter,double epsilon)
{
/* This is not sparce method */
/* Make optimization using */
/* func - function to compute */
/* uses function to compute jacobian */
/* Allocate memory */
CvMat *vectX = 0;
CvMat *vectNewX = 0;
CvMat *resFunc = 0;
CvMat *resNewFunc = 0;
CvMat *error = 0;
CvMat *errorNew = 0;
CvMat *Jac = 0;
CvMat *delta = 0;
CvMat *matrJtJ = 0;
CvMat *matrJtJN = 0;
CvMat *matrJt = 0;
CvMat *vectB = 0;
CV_FUNCNAME( "cvLevenbegrMarquardtOptimization" );
__BEGIN__;
if( JacobianFunction == 0 || function == 0 || X0 == 0 || observRes == 0 || resultX == 0 )
{
CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
}
if( !CV_IS_MAT(X0) || !CV_IS_MAT(observRes) || !CV_IS_MAT(resultX) )
{
CV_ERROR( CV_StsUnsupportedFormat, "Some of input parameters must be a matrices" );
}
int numVal;
int numFunc;
double valError;
double valNewError;
numVal = X0->rows;
numFunc = observRes->rows;
/* test input data */
if( X0->cols != 1 )
{
CV_ERROR( CV_StsUnmatchedSizes, "Number of colomn of vector X0 must be 1" );
}
if( observRes->cols != 1 )
{
CV_ERROR( CV_StsUnmatchedSizes, "Number of colomn of vector observed rusult must be 1" );
}
if( resultX->cols != 1 || resultX->rows != numVal )
{
CV_ERROR( CV_StsUnmatchedSizes, "Size of result vector X must be equals to X0" );
}
if( maxIter <= 0 )
{
CV_ERROR( CV_StsUnmatchedSizes, "Number of maximum iteration must be > 0" );
}
if( epsilon < 0 )
{
CV_ERROR( CV_StsUnmatchedSizes, "Epsilon must be >= 0" );
}
/* copy x0 to current value of x */
CV_CALL( vectX = cvCreateMat(numVal, 1, CV_64F) );
CV_CALL( vectNewX = cvCreateMat(numVal, 1, CV_64F) );
CV_CALL( resFunc = cvCreateMat(numFunc,1, CV_64F) );
CV_CALL( resNewFunc = cvCreateMat(numFunc,1, CV_64F) );
CV_CALL( error = cvCreateMat(numFunc,1, CV_64F) );
CV_CALL( errorNew = cvCreateMat(numFunc,1, CV_64F) );
CV_CALL( Jac = cvCreateMat(numFunc,numVal, CV_64F) );
CV_CALL( delta = cvCreateMat(numVal, 1, CV_64F) );
CV_CALL( matrJtJ = cvCreateMat(numVal, numVal, CV_64F) );
CV_CALL( matrJtJN = cvCreateMat(numVal, numVal, CV_64F) );
CV_CALL( matrJt = cvCreateMat(numVal, numFunc,CV_64F) );
CV_CALL( vectB = cvCreateMat(numVal, 1, CV_64F) );
cvCopy(X0,vectX);
/* ========== Main optimization loop ============ */
double change;
int currIter;
double alpha;
change = 1;
currIter = 0;
alpha = 0.001;
do {
/* Compute value of function */
function(vectX,resFunc);
/* Print result of function to file */
/* Compute error */
cvSub(observRes,resFunc,error);
//valError = error_function(observRes,resFunc);
/* Need to use new version of computing error (norm) */
valError = cvNorm(observRes,resFunc);
/* Compute Jacobian for given point vectX */
JacobianFunction(vectX,Jac);
/* Define optimal delta for J'*J*delta=J'*error */
/* compute J'J */
cvMulTransposed(Jac,matrJtJ,1);
cvCopy(matrJtJ,matrJtJN);
/* compute J'*error */
cvTranspose(Jac,matrJt);
cvmMul(matrJt,error,vectB);
/* Solve normal equation for given alpha and Jacobian */
do
{
/* Increase diagonal elements by alpha */
for( int i = 0; i < numVal; i++ )
{
double val;
val = cvmGet(matrJtJ,i,i);
cvmSet(matrJtJN,i,i,(1+alpha)*val);
}
/* Solve system to define delta */
cvSolve(matrJtJN,vectB,delta,CV_SVD);
/* We know delta and we can define new value of vector X */
cvAdd(vectX,delta,vectNewX);
/* Compute result of function for new vector X */
function(vectNewX,resNewFunc);
cvSub(observRes,resNewFunc,errorNew);
valNewError = cvNorm(observRes,resNewFunc);
currIter++;
if( valNewError < valError )
{/* accept new value */
valError = valNewError;
/* Compute relative change of required parameter vectorX. change = norm(curr-prev) / norm(curr) ) */
change = cvNorm(vectX, vectNewX, CV_RELATIVE_L2);
alpha /= 10;
cvCopy(vectNewX,vectX);
break;
}
else
{
alpha *= 10;
}
} while ( currIter < maxIter );
/* new value of X and alpha were accepted */
} while ( change > epsilon && currIter < maxIter );
/* result was computed */
cvCopy(vectX,resultX);
__END__;
cvReleaseMat(&vectX);
cvReleaseMat(&vectNewX);
cvReleaseMat(&resFunc);
cvReleaseMat(&resNewFunc);
cvReleaseMat(&error);
cvReleaseMat(&errorNew);
cvReleaseMat(&Jac);
cvReleaseMat(&delta);
cvReleaseMat(&matrJtJ);
cvReleaseMat(&matrJtJN);
cvReleaseMat(&matrJt);
cvReleaseMat(&vectB);
return;
}
/*------------------------------------------------------------------------------*/
#if 0
//tests
void Jac_Func2(CvMat *vectX,CvMat *Jac)
{
double x = cvmGet(vectX,0,0);
double y = cvmGet(vectX,1,0);
cvmSet(Jac,0,0,2*(x-2));
cvmSet(Jac,0,1,2*(y+3));
cvmSet(Jac,1,0,1);
cvmSet(Jac,1,1,1);
return;
}
void Res_Func2(CvMat *vectX,CvMat *res)
{
double x = cvmGet(vectX,0,0);
double y = cvmGet(vectX,1,0);
cvmSet(res,0,0,(x-2)*(x-2)+(y+3)*(y+3));
cvmSet(res,1,0,x+y);
return;
}
double Err_Func2(CvMat *obs,CvMat *res)
{
CvMat *tmp;
tmp = cvCreateMat(obs->rows,1,CV_64F);
cvSub(obs,res,tmp);
double e;
e = cvNorm(tmp);
return e;
}
void TestOptimX2Y2()
{
CvMat vectX0;
double vectX0_dat[2];
vectX0 = cvMat(2,1,CV_64F,vectX0_dat);
vectX0_dat[0] = 5;
vectX0_dat[1] = -7;
CvMat observRes;
double observRes_dat[2];
observRes = cvMat(2,1,CV_64F,observRes_dat);
observRes_dat[0] = 0;
observRes_dat[1] = -1;
observRes_dat[0] = 0;
observRes_dat[1] = -1.2;
CvMat optimX;
double optimX_dat[2];
optimX = cvMat(2,1,CV_64F,optimX_dat);
LevenbegrMarquardtOptimization( Jac_Func2, Res_Func2, Err_Func2,
&vectX0,&observRes,&optimX,100,0.000001);
return;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,495 @@
/*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 <float.h>
#include <limits.h>
/* Valery Mosyagin */
typedef void (*pointer_LMJac)( const CvMat* src, CvMat* dst );
typedef void (*pointer_LMFunc)( const CvMat* src, CvMat* dst );
void cvLevenbergMarquardtOptimization(pointer_LMJac JacobianFunction,
pointer_LMFunc function,
/*pointer_Err error_function,*/
CvMat *X0,CvMat *observRes,CvMat *resultX,
int maxIter,double epsilon);
void icvReconstructPointsFor3View( CvMat* projMatr1,CvMat* projMatr2,CvMat* projMatr3,
CvMat* projPoints1,CvMat* projPoints2,CvMat* projPoints3,
CvMat* points4D);
/* Jacobian computation for trifocal case */
void icvJacobianFunction_ProjTrifocal(const CvMat *vectX,CvMat *Jacobian)
{
CV_FUNCNAME( "icvJacobianFunction_ProjTrifocal" );
__BEGIN__;
/* Test data for errors */
if( vectX == 0 || Jacobian == 0 )
{
CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
}
if( !CV_IS_MAT(vectX) || !CV_IS_MAT(Jacobian) )
{
CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
}
int numPoints;
numPoints = (vectX->rows - 36)/4;
if( numPoints < 1 )//!!! Need to correct this minimal number of points
{
CV_ERROR( CV_StsUnmatchedSizes, "number of points must be more than 0" );
}
if( Jacobian->rows == numPoints*6 || Jacobian->cols != 36+numPoints*4 )
{
CV_ERROR( CV_StsUnmatchedSizes, "Size of Jacobian is not correct it must be 6*numPoints x (36+numPoints*4)" );
}
/* Computed Jacobian in a given point */
/* This is for function with 3 projection matrices */
/* vector X consists of projection matrices and points3D */
/* each 3D points has X,Y,Z,W */
/* each projection matrices has 3x4 coeffs */
/* For N points 4D we have Jacobian 2N x (12*3+4N) */
/* Will store derivates as */
/* Fill Jacobian matrix */
int currProjPoint;
int currMatr;
cvZero(Jacobian);
for( currMatr = 0; currMatr < 3; currMatr++ )
{
double p[12];
for( int i=0;i<12;i++ )
{
p[i] = cvmGet(vectX,currMatr*12+i,0);
}
int currVal = 36;
for( currProjPoint = 0; currProjPoint < numPoints; currProjPoint++ )
{
/* Compute */
double X[4];
X[0] = cvmGet(vectX,currVal++,0);
X[1] = cvmGet(vectX,currVal++,0);
X[2] = cvmGet(vectX,currVal++,0);
X[3] = cvmGet(vectX,currVal++,0);
double piX[3];
piX[0] = X[0]*p[0] + X[1]*p[1] + X[2]*p[2] + X[3]*p[3];
piX[1] = X[0]*p[4] + X[1]*p[5] + X[2]*p[6] + X[3]*p[7];
piX[2] = X[0]*p[8] + X[1]*p[9] + X[2]*p[10] + X[3]*p[11];
int i,j;
/* fill derivate by point */
double tmp3 = 1/(piX[2]*piX[2]);
double tmp1 = -piX[0]*tmp3;
double tmp2 = -piX[1]*tmp3;
for( j = 0; j < 2; j++ )//for x and y
{
for( i = 0; i < 4; i++ )// for X,Y,Z,W
{
cvmSet( Jacobian,
currMatr*numPoints*2+currProjPoint*2+j, 36+currProjPoint*4+i,
(p[j*4+i]*piX[2]-p[8+i]*piX[j]) * tmp3 );
}
}
/* fill derivate by projection matrix */
for( i = 0; i < 4; i++ )
{
/* derivate for x */
cvmSet(Jacobian,currMatr*numPoints*2+currProjPoint*2,currMatr*12+i,X[i]/piX[2]);//x' p1i
cvmSet(Jacobian,currMatr*numPoints*2+currProjPoint*2,currMatr*12+8+i,X[i]*tmp1);//x' p3i
/* derivate for y */
cvmSet(Jacobian,currMatr*numPoints*2+currProjPoint*2+1,currMatr*12+4+i,X[i]/piX[2]);//y' p2i
cvmSet(Jacobian,currMatr*numPoints*2+currProjPoint*2+1,currMatr*12+8+i,X[i]*tmp2);//y' p3i
}
}
}
__END__;
return;
}
void icvFunc_ProjTrifocal(const CvMat *vectX, CvMat *resFunc)
{
/* Computes function in a given point */
/* Computers project points using 3 projection matrices and points 3D */
/* vector X consists of projection matrices and points3D */
/* each projection matrices has 3x4 coeffs */
/* each 3D points has X,Y,Z,W(?) */
/* result of function is projection of N 3D points using 3 projection matrices */
/* projected points store as (projection by matrix P1),(projection by matrix P2),(projection by matrix P3) */
/* each projection is x1,y1,x2,y2,x3,y3,x4,y4 */
/* Compute projection of points */
/* Fill projection matrices */
CV_FUNCNAME( "icvFunc_ProjTrifocal" );
__BEGIN__;
/* Test data for errors */
if( vectX == 0 || resFunc == 0 )
{
CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
}
if( !CV_IS_MAT(vectX) || !CV_IS_MAT(resFunc) )
{
CV_ERROR( CV_StsUnsupportedFormat, "Input parameters must be a matrices" );
}
int numPoints;
numPoints = (vectX->rows - 36)/4;
if( numPoints < 1 )//!!! Need to correct this minimal number of points
{
CV_ERROR( CV_StsUnmatchedSizes, "number of points must be more than 0" );
}
if( resFunc->rows == 2*numPoints*3 || resFunc->cols != 1 )
{
CV_ERROR( CV_StsUnmatchedSizes, "Size of resFunc is not correct it must be 2*numPoints*3 x 1");
}
CvMat projMatrs[3];
double projMatrs_dat[36];
projMatrs[0] = cvMat(3,4,CV_64F,projMatrs_dat);
projMatrs[1] = cvMat(3,4,CV_64F,projMatrs_dat+12);
projMatrs[2] = cvMat(3,4,CV_64F,projMatrs_dat+24);
CvMat point3D;
double point3D_dat[3];
point3D = cvMat(3,1,CV_64F,point3D_dat);
int currMatr;
int currV;
int i,j;
currV=0;
for( currMatr = 0; currMatr < 3; currMatr++ )
{
for( i = 0; i < 3; i++ )
{
for( j = 0;j < 4; j++ )
{
double val = cvmGet(vectX,currV,0);
cvmSet(&projMatrs[currMatr],i,j,val);
currV++;
}
}
}
/* Project points */
int currPoint;
CvMat point4D;
double point4D_dat[4];
point4D = cvMat(4,1,CV_64F,point4D_dat);
for( currPoint = 0; currPoint < numPoints; currPoint++ )
{
/* get curr point */
point4D_dat[0] = cvmGet(vectX,currV++,0);
point4D_dat[1] = cvmGet(vectX,currV++,0);
point4D_dat[2] = cvmGet(vectX,currV++,0);
point4D_dat[3] = cvmGet(vectX,currV++,0);
for( currMatr = 0; currMatr < 3; currMatr++ )
{
/* Compute projection for current point */
cvmMul(&projMatrs[currMatr],&point4D,&point3D);
double z = point3D_dat[2];
cvmSet(resFunc,currMatr*numPoints*2 + currPoint*2, 0,point3D_dat[0]/z);
cvmSet(resFunc,currMatr*numPoints*2 + currPoint*2+1,0,point3D_dat[1]/z);
}
}
__END__;
return;
}
/*----------------------------------------------------------------------------------------*/
void icvOptimizeProjectionTrifocal(CvMat **projMatrs,CvMat **projPoints,
CvMat **resultProjMatrs, CvMat *resultPoints4D)
{
CvMat *optimX = 0;
CvMat *points4D = 0;
CvMat *vectorX0 = 0;
CvMat *observRes = 0;
//CvMat *error = 0;
CV_FUNCNAME( "icvOptimizeProjectionTrifocal" );
__BEGIN__;
/* Test data for errors */
if( projMatrs == 0 || projPoints == 0 || resultProjMatrs == 0 || resultPoints4D == 0)
{
CV_ERROR( CV_StsNullPtr, "Some of parameters is a NULL pointer" );
}
if( !CV_IS_MAT(resultPoints4D) )
{
CV_ERROR( CV_StsUnsupportedFormat, "resultPoints4D must be a matrix" );
}
int numPoints;
numPoints = resultPoints4D->cols;
if( numPoints < 1 )
{
CV_ERROR( CV_StsOutOfRange, "Number points of resultPoints4D must be more than 0" );
}
if( resultPoints4D->rows != 4 )
{
CV_ERROR( CV_StsUnmatchedSizes, "Number of coordinates of points4D must be 4" );
}
int i;
for( i = 0; i < 3; i++ )
{
if( projMatrs[i] == 0 )
{
CV_ERROR( CV_StsNullPtr, "Some of projMatrs is a NULL pointer" );
}
if( projPoints[i] == 0 )
{
CV_ERROR( CV_StsNullPtr, "Some of projPoints is a NULL pointer" );
}
if( resultProjMatrs[i] == 0 )
{
CV_ERROR( CV_StsNullPtr, "Some of resultProjMatrs is a NULL pointer" );
}
/* ----------- test for matrix ------------- */
if( !CV_IS_MAT(projMatrs[i]) )
{
CV_ERROR( CV_StsUnsupportedFormat, "Each of projMatrs must be a matrix" );
}
if( !CV_IS_MAT(projPoints[i]) )
{
CV_ERROR( CV_StsUnsupportedFormat, "Each of projPoints must be a matrix" );
}
if( !CV_IS_MAT(resultProjMatrs[i]) )
{
CV_ERROR( CV_StsUnsupportedFormat, "Each of resultProjMatrs must be a matrix" );
}
/* ------------- Test sizes --------------- */
if( projMatrs[i]->rows != 3 || projMatrs[i]->cols != 4 )
{
CV_ERROR( CV_StsUnmatchedSizes, "Size of projMatr must be 3x4" );
}
if( projPoints[i]->rows != 2 || projPoints[i]->cols != numPoints )
{
CV_ERROR( CV_StsUnmatchedSizes, "Size of resultProjMatrs must be 3x4" );
}
if( resultProjMatrs[i]->rows != 3 || resultProjMatrs[i]->cols != 4 )
{
CV_ERROR( CV_StsUnmatchedSizes, "Size of resultProjMatrs must be 3x4" );
}
}
/* Allocate memory for points 4D */
CV_CALL( points4D = cvCreateMat(4,numPoints,CV_64F) );
CV_CALL( vectorX0 = cvCreateMat(36 + numPoints*4,1,CV_64F) );
CV_CALL( observRes = cvCreateMat(2*numPoints*3,1,CV_64F) );
CV_CALL( optimX = cvCreateMat(36+numPoints*4,1,CV_64F) );
//CV_CALL( error = cvCreateMat(numPoints*2*3,1,CV_64F) );
/* Reconstruct points 4D using projected points and projection matrices */
icvReconstructPointsFor3View( projMatrs[0],projMatrs[1],projMatrs[2],
projPoints[0],projPoints[1],projPoints[2],
points4D);
/* Fill observed points on images */
/* result of function is projection of N 3D points using 3 projection matrices */
/* projected points store as (projection by matrix P1),(projection by matrix P2),(projection by matrix P3) */
/* each projection is x1,y1,x2,y2,x3,y3,x4,y4 */
int currMatr;
for( currMatr = 0; currMatr < 3; currMatr++ )
{
for( i = 0; i < numPoints; i++ )
{
cvmSet(observRes,currMatr*numPoints*2+i*2 ,0,cvmGet(projPoints[currMatr],0,i) );/* x */
cvmSet(observRes,currMatr*numPoints*2+i*2+1,0,cvmGet(projPoints[currMatr],1,i) );/* y */
}
}
/* Fill with projection matrices */
for( currMatr = 0; currMatr < 3; currMatr++ )
{
int i;
for( i = 0; i < 12; i++ )
{
cvmSet(vectorX0,currMatr*12+i,0,cvmGet(projMatrs[currMatr],i/4,i%4));
}
}
/* Fill with 4D points */
int currPoint;
for( currPoint = 0; currPoint < numPoints; currPoint++ )
{
cvmSet(vectorX0,36 + currPoint*4 + 0,0,cvmGet(points4D,0,currPoint));
cvmSet(vectorX0,36 + currPoint*4 + 1,0,cvmGet(points4D,1,currPoint));
cvmSet(vectorX0,36 + currPoint*4 + 2,0,cvmGet(points4D,2,currPoint));
cvmSet(vectorX0,36 + currPoint*4 + 3,0,cvmGet(points4D,3,currPoint));
}
/* Allocate memory for result */
cvLevenbergMarquardtOptimization( icvJacobianFunction_ProjTrifocal, icvFunc_ProjTrifocal,
vectorX0,observRes,optimX,100,1e-6);
/* Copy results */
for( currMatr = 0; currMatr < 3; currMatr++ )
{
/* Copy projection matrices */
for(int i=0;i<12;i++)
{
cvmSet(resultProjMatrs[currMatr],i/4,i%4,cvmGet(optimX,currMatr*12+i,0));
}
}
/* Copy 4D points */
for( currPoint = 0; currPoint < numPoints; currPoint++ )
{
cvmSet(resultPoints4D,0,currPoint,cvmGet(optimX,36 + currPoint*4,0));
cvmSet(resultPoints4D,1,currPoint,cvmGet(optimX,36 + currPoint*4+1,0));
cvmSet(resultPoints4D,2,currPoint,cvmGet(optimX,36 + currPoint*4+2,0));
cvmSet(resultPoints4D,3,currPoint,cvmGet(optimX,36 + currPoint*4+3,0));
}
__END__;
/* Free allocated memory */
cvReleaseMat(&optimX);
cvReleaseMat(&points4D);
cvReleaseMat(&vectorX0);
cvReleaseMat(&observRes);
return;
}
/*------------------------------------------------------------------------------*/
/* Create good points using status information */
void icvCreateGoodPoints(CvMat *points,CvMat **goodPoints, CvMat *status)
{
*goodPoints = 0;
CV_FUNCNAME( "icvCreateGoodPoints" );
__BEGIN__;
int numPoints;
numPoints = points->cols;
if( numPoints < 1 )
{
CV_ERROR( CV_StsOutOfRange, "Number of points must be more than 0" );
}
int numCoord;
numCoord = points->rows;
if( numCoord < 1 )
{
CV_ERROR( CV_StsOutOfRange, "Number of points coordinates must be more than 0" );
}
/* Define number of good points */
int goodNum;
int i,j;
goodNum = 0;
for( i = 0; i < numPoints; i++)
{
if( cvmGet(status,0,i) > 0 )
goodNum++;
}
/* Allocate memory for good points */
CV_CALL( *goodPoints = cvCreateMat(numCoord,goodNum,CV_64F) );
for( i = 0; i < numCoord; i++ )
{
int currPoint = 0;
for( j = 0; j < numPoints; j++)
{
if( cvmGet(status,0,j) > 0 )
{
cvmSet(*goodPoints,i,currPoint,cvmGet(points,i,j));
currPoint++;
}
}
}
__END__;
return;
}

View File

@@ -0,0 +1,480 @@
/*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"
#if 0
CvStatus
icvFetchLine8uC3R( uchar * src, int src_step,
uchar * dst, int *dst_num, CvSize src_size, CvPoint start, CvPoint end )
{
int i;
int dx = end.x - start.x, dy = end.y - start.y;
int err;
if( !src || !dst || (src_size.width | src_size.height) < 0 ||
src_step < src_size.width * 3 ||
(unsigned) start.x >= (unsigned) src_size.width ||
(unsigned) start.y >= (unsigned) src_size.height ||
(unsigned) end.x >= (unsigned) src_size.width ||
(unsigned) end.y >= (unsigned) src_size.height )
return CV_BADFACTOR_ERR;
if( dx < 0 )
{
dx = -dx;
dy = -dy;
start.x = end.x;
start.y = end.y;
}
src += start.y * src_step + start.x * 3;
i = dy >> 31;
dy = (dy ^ i) - i;
src_step = (src_step ^ i) - i;
if( dx > dy )
{
if( dst_num )
{
if( *dst_num <= dx )
return CV_BADSIZE_ERR;
*dst_num = dx + 1;
}
err = dx;
dx += dx;
dy += dy;
for( i = dx; i >= 0; i -= 2, dst += 3 )
{
int mask = (err -= dy) < 0 ? -1 : 0;
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
err += dx & mask;
src += (src_step & mask) + 3;
}
}
else
{
if( dst_num )
{
if( *dst_num <= dy )
return CV_BADSIZE_ERR;
*dst_num = dy + 1;
}
err = dy;
dx += dx;
dy += dy;
for( i = dy; i >= 0; i -= 2, dst += 3 )
{
int mask = (err -= dx) < 0 ? -1 : 0;
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
err += dy & mask;
src += src_step + (mask & 3);
}
}
return CV_NO_ERR;
}
CvStatus
icvDrawLine8uC3R( uchar * src, int src_num,
uchar * dst, int dst_step, CvSize dst_size, CvPoint start, CvPoint end )
{
int i;
int dx = end.x - start.x, dy = end.y - start.y;
int err;
if( !src || !dst || (dst_size.width | dst_size.height) < 0 ||
dst_step < dst_size.width * 3 ||
(unsigned) start.x >= (unsigned) dst_size.width ||
(unsigned) start.y >= (unsigned) dst_size.height ||
(unsigned) end.x >= (unsigned) dst_size.width ||
(unsigned) end.y >= (unsigned) dst_size.height )
return CV_BADFACTOR_ERR;
if( dx < 0 )
{
dx = -dx;
dy = -dy;
start.x = end.x;
start.y = end.y;
}
dst += start.y * dst_step + start.x * 3;
i = dy >> 31;
dy = (dy ^ i) - i;
dst_step = (dst_step ^ i) - i;
if( dx > dy )
{
if( (unsigned) (src_num - 1) < (unsigned) dx )
return CV_BADSIZE_ERR;
err = dx;
dx += dx;
dy += dy;
for( i = dx; i >= 0; i -= 2, src += 3 )
{
int mask = (err -= dy) < 0 ? -1 : 0;
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
err += dx & mask;
dst += (dst_step & mask) + 3;
}
}
else
{
if( (unsigned) (src_num - 1) < (unsigned) dy )
return CV_BADSIZE_ERR;
err = dy;
dx += dx;
dy += dy;
for( i = dy; i >= 0; i -= 2, src += 3 )
{
int mask = (err -= dx) < 0 ? -1 : 0;
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
err += dy & mask;
dst += dst_step + (mask & 3);
}
}
return CV_NO_ERR;
}
#endif
/*======================================================================================*/
static CvStatus
icvPreWarpImage8uC3R( int numLines, /* number of scanlines */
uchar * src, /* source image */
int src_step, /* line step */
uchar * dst, /* dest buffers */
int *dst_nums, /* lens of buffer */
CvSize src_size, /* image size in pixels */
int *scanlines ) /* scanlines array */
{
int k;
CvPoint start;
CvPoint end;
int curr;
int curr_dst;
CvMat mat;
curr = 0;
curr_dst = 0;
cvInitMatHeader( &mat, src_size.height, src_size.width, CV_8UC3, src, src_step );
for( k = 0; k < numLines; k++ )
{
start.x = scanlines[curr++];
start.y = scanlines[curr++];
end.x = scanlines[curr++];
end.y = scanlines[curr++];
#ifdef _DEBUG
{
CvLineIterator iterator;
assert( cvInitLineIterator( &mat, start, end, &iterator, 8 ) == dst_nums[k] );
}
#endif
cvSampleLine( &mat, start, end, dst + curr_dst, 8 );
curr_dst += dst_nums[k] * 3;
}
return CV_NO_ERR;
}
/*======================================================================================*/
static CvStatus
icvPostWarpImage8uC3R( int numLines, /* number of scanlines */
uchar * src, /* source buffers */
int *src_nums, /* lens of buffers */
uchar * dst, /* dest image */
int dst_step, /* dest image step */
CvSize dst_size, /* dest image size */
int *scanlines ) /* scanline */
{
int i, k;
CvPoint start;
CvPoint end;
int curr;
int src_num;
int curr_src;
CvMat mat;
CvLineIterator iterator;
curr = 0;
curr_src = 0;
cvInitMatHeader( &mat, dst_size.height, dst_size.width, CV_8UC3, dst, dst_step );
for( k = 0; k < numLines; k++ )
{
start.x = scanlines[curr++];
start.y = scanlines[curr++];
end.x = scanlines[curr++];
end.y = scanlines[curr++];
src_num = src_nums[k];
if( cvInitLineIterator( &mat, start, end, &iterator, 8 ) != src_num )
{
assert(0);
return CV_NOTDEFINED_ERR;
}
for( i = 0; i < src_num; i++ )
{
memcpy( iterator.ptr, src + curr_src, 3 );
CV_NEXT_LINE_POINT( iterator );
curr_src += 3;
}
#if 0
err = icvDrawLine8uC3R( src + curr_src, /* sourse buffer */
src_num, /* len of buffer */
dst, /* dest image */
dst_step, /* dest image step */
dst_size, /* dest image size */
start, /* start point */
end ); /* end point */
curr_src += src_num * 3;
#endif
}
return CV_NO_ERR;
}
/*======================================================================================*/
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: icvDeleteMoire8uC3R
// Purpose:
// Function deletes moire - replaces black uncovered pixels with their neighboors.
// Context:
// Parameters:
// img - image data
// img_step - distance between lines in bytes
// img_size - width and height of the image in pixels
// Returns:
// CV_NO_ERR if all Ok or error code
// Notes:
//F*/
static CvStatus
icvDeleteMoire8u( uchar * img, int img_step, CvSize img_size, int cn )
{
int x, y;
uchar *src = img, *dst = img + img_step;
if( !img || img_size.width <= 0 || img_size.height <= 0 || img_step < img_size.width * 3 )
return CV_BADFACTOR_ERR;
img_size.width *= cn;
for( y = 1; y < img_size.height; y++, src = dst, dst += img_step )
{
switch( cn )
{
case 1:
for( x = 0; x < img_size.width; x++ )
{
if( dst[x] == 0 )
dst[x] = src[x];
}
break;
case 3:
for( x = 0; x < img_size.width; x += 3 )
{
if( dst[x] == 0 && dst[x + 1] == 0 && dst[x + 2] == 0 )
{
dst[x] = src[x];
dst[x + 1] = src[x + 1];
dst[x + 2] = src[x + 2];
}
}
break;
default:
assert(0);
break;
}
}
return CV_NO_ERR;
}
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvDeleteMoire
// Purpose: The functions delete moire on the image after ViewMorphing
// Context:
// Parameters: img - image on which will delete moire
//
// Notes:
//F*/
CV_IMPL void
cvDeleteMoire( IplImage * img )
{
uchar *img_data = 0;
int img_step = 0;
CvSize img_size;
CV_FUNCNAME( "cvDeleteMoire" );
__BEGIN__;
cvGetImageRawData( img, &img_data, &img_step, &img_size );
if( img->nChannels != 1 && img->nChannels != 3 )
CV_ERROR( CV_BadNumChannels, "Source image must have 3 channel." );
if( img->depth != IPL_DEPTH_8U )
CV_ERROR( CV_BadDepth, "Channel depth of source image must be 8." );
CV_CALL( icvDeleteMoire8u( img_data, img_step, img_size, img->nChannels ));
__END__;
}
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvPreWarpImage
// Purpose: The functions warp image for next stage of ViewMorphing
// Context:
// Parameters: img - initial image (in the beginning)
//
// Notes:
//F*/
CV_IMPL void
cvPreWarpImage( int numLines, /* number of scanlines */
IplImage * img, /* Source Image */
uchar * dst, /* dest buffers */
int *dst_nums, /* lens of buffer */
int *scanlines /* scanlines array */ )
{
uchar *img_data = 0;
int img_step = 0;
CvSize img_size;
CV_FUNCNAME( "cvPreWarpImage" );
__BEGIN__;
cvGetImageRawData( img, &img_data, &img_step, &img_size );
if( img->nChannels != 3 )
CV_ERROR( CV_BadNumChannels, "Source image must have 3 channel." );
if( img->depth != IPL_DEPTH_8U )
CV_ERROR( CV_BadDepth, "Channel depth of image must be 8." );
CV_CALL( icvPreWarpImage8uC3R( numLines, /* number of scanlines */
img_data, /* source image */
img_step, /* line step */
dst, /* dest buffers */
dst_nums, /* lens of buffer */
img_size, /* image size in pixels */
scanlines /* scanlines array */ ));
__END__;
}
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: cvPostWarpImage
// Purpose: The functions postwarp the image after morphing
// Context:
// Parameters: img - initial image (in the beginning)
//
// Notes:
//F*/
CV_IMPL void
cvPostWarpImage( int numLines, /* number of scanlines */
uchar * src, /* source buffers */
int *src_nums, /* lens of buffers */
IplImage * img, /* dest image */
int *scanlines /* scanline */ )
{
uchar *img_data = 0;
int img_step = 0;
CvSize img_size;
CV_FUNCNAME( "cvPostWarpImage" );
__BEGIN__;
cvGetImageRawData( img, &img_data, &img_step, &img_size );
if( img->nChannels != 3 )
CV_ERROR( CV_BadNumChannels, "Source image must have 3 channel." );
if( img->depth != IPL_DEPTH_8U )
CV_ERROR( CV_BadDepth, "Channel depth of image must be 8." );
CV_CALL( icvPostWarpImage8uC3R( numLines, /* number of scanlines */
src, /* source buffers */
src_nums, /* lens of buffers */
img_data, /* dest image */
img_step, /* dest image step */
img_size, /* dest image size */
scanlines /* scanline */ ));
__END__;
}
/* End of file */

1766
modules/legacy/src/lmeds.cpp Normal file

File diff suppressed because it is too large Load Diff

879
modules/legacy/src/mat.cpp Normal file
View File

@@ -0,0 +1,879 @@
/*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"
// temporarily remove it from build
#if 0 && ((_MSC_VER>=1200) || defined __BORLANDC__)
double CvMAT::get( const uchar* ptr, int type, int coi )
{
double t = 0;
assert( (unsigned)coi < (unsigned)CV_MAT_CN(type) );
switch( CV_MAT_DEPTH(type) )
{
case CV_8U:
t = ((uchar*)ptr)[coi];
break;
case CV_8S:
t = ((char*)ptr)[coi];
break;
case CV_16S:
t = ((short*)ptr)[coi];
break;
case CV_32S:
t = ((int*)ptr)[coi];
break;
case CV_32F:
t = ((float*)ptr)[coi];
break;
case CV_64F:
t = ((double*)ptr)[coi];
break;
}
return t;
}
void CvMAT::set( uchar* ptr, int type, int coi, double d )
{
int i;
assert( (unsigned)coi < (unsigned)CV_MAT_CN(type) );
switch( CV_MAT_DEPTH(type))
{
case CV_8U:
i = cvRound(d);
((uchar*)ptr)[coi] = CV_CAST_8U(i);
break;
case CV_8S:
i = cvRound(d);
((char*)ptr)[coi] = CV_CAST_8S(i);
break;
case CV_16S:
i = cvRound(d);
((short*)ptr)[coi] = CV_CAST_16S(i);
break;
case CV_32S:
i = cvRound(d);
((int*)ptr)[coi] = CV_CAST_32S(i);
break;
case CV_32F:
((float*)ptr)[coi] = (float)d;
break;
case CV_64F:
((double*)ptr)[coi] = d;
break;
}
}
void CvMAT::set( uchar* ptr, int type, int coi, int i )
{
assert( (unsigned)coi < (unsigned)CV_MAT_CN(type) );
switch( CV_MAT_DEPTH(type))
{
case CV_8U:
((uchar*)ptr)[coi] = CV_CAST_8U(i);
break;
case CV_8S:
((char*)ptr)[coi] = CV_CAST_8S(i);
break;
case CV_16S:
((short*)ptr)[coi] = CV_CAST_16S(i);
break;
case CV_32S:
((int*)ptr)[coi] = i;
break;
case CV_32F:
((float*)ptr)[coi] = (float)i;
break;
case CV_64F:
((double*)ptr)[coi] = (double)i;
break;
}
}
void CvMAT::set( uchar* ptr, int type, double d )
{
int i, cn = CV_MAT_CN(type);
switch( CV_MAT_DEPTH(type))
{
case CV_8U:
i = cvRound(d);
((uchar*)ptr)[0] = CV_CAST_8U(i);
i = cn;
while( --i ) ((uchar*)ptr)[i] = 0;
break;
case CV_8S:
i = cvRound(d);
((char*)ptr)[0] = CV_CAST_8S(i);
i = cn;
while( --i ) ((char*)ptr)[i] = 0;
break;
case CV_16S:
i = cvRound(d);
((short*)ptr)[0] = CV_CAST_16S(i);
i = cn;
while( --i ) ((short*)ptr)[i] = 0;
break;
case CV_32S:
i = cvRound(d);
((int*)ptr)[0] = i;
i = cn;
while( --i ) ((int*)ptr)[i] = 0;
break;
case CV_32F:
((float*)ptr)[0] = (float)d;
i = cn;
while( --i ) ((float*)ptr)[i] = 0;
break;
case CV_64F:
((double*)ptr)[0] = d;
i = cn;
while( --i ) ((double*)ptr)[i] = 0;
break;
}
}
void CvMAT::set( uchar* ptr, int type, int i )
{
int cn = CV_MAT_CN(type);
switch( CV_MAT_DEPTH(type))
{
case CV_8U:
((uchar*)ptr)[0] = CV_CAST_8U(i);
i = cn;
while( --i ) ((uchar*)ptr)[i] = 0;
break;
case CV_8S:
((char*)ptr)[0] = CV_CAST_8S(i);
i = cn;
while( --i ) ((char*)ptr)[i] = 0;
break;
case CV_16S:
((short*)ptr)[0] = CV_CAST_16S(i);
i = cn;
while( --i ) ((short*)ptr)[i] = 0;
break;
case CV_32S:
((int*)ptr)[0] = i;
i = cn;
while( --i ) ((int*)ptr)[i] = 0;
break;
case CV_32F:
((float*)ptr)[0] = (float)i;
i = cn;
while( --i ) ((float*)ptr)[i] = 0;
break;
case CV_64F:
((double*)ptr)[0] = (double)i;
i = cn;
while( --i ) ((double*)ptr)[i] = 0;
break;
}
}
CvMAT::CvMAT( const _CvMAT_T_& mat_t )
{
data.ptr = 0;
type = 0;
refcount = 0;
*this = mat_t;
}
CvMAT::CvMAT( const _CvMAT_ADD_& mat_add )
{
data.ptr = 0;
type = 0;
refcount = 0;
*this = mat_add;
}
CvMAT::CvMAT( const _CvMAT_ADD_EX_& mat_add )
{
data.ptr = 0;
type = 0;
refcount = 0;
*this = mat_add;
}
CvMAT::CvMAT( const _CvMAT_SCALE_& scale_mat )
{
data.ptr = 0;
type = 0;
refcount = 0;
*this = scale_mat;
}
CvMAT::CvMAT( const _CvMAT_SCALE_SHIFT_& scale_shift_mat )
{
data.ptr = 0;
type = 0;
refcount = 0;
*this = scale_shift_mat;
}
CvMAT::CvMAT( const _CvMAT_MUL_& mmul )
{
data.ptr = 0;
type = 0;
refcount = 0;
*this = mmul;
}
CvMAT::CvMAT( const _CvMAT_MUL_ADD_& mmuladd )
{
data.ptr = 0;
type = 0;
refcount = 0;
*this = mmuladd;
}
CvMAT::CvMAT( const _CvMAT_INV_& inv_mat )
{
data.ptr = 0;
type = 0;
refcount = 0;
*this = inv_mat;
}
CvMAT::CvMAT( const _CvMAT_NOT_& not_mat )
{
type = 0;
data.ptr = 0;
refcount = 0;
*this = not_mat;
}
CvMAT::CvMAT( const _CvMAT_UN_LOGIC_& mat_logic )
{
type = 0;
data.ptr = 0;
refcount = 0;
*this = mat_logic;
}
CvMAT::CvMAT( const _CvMAT_LOGIC_& mat_logic )
{
type = 0;
data.ptr = 0;
refcount = 0;
*this = mat_logic;
}
CvMAT::CvMAT( const _CvMAT_COPY_& mat_copy )
{
CvMAT* src = (CvMAT*)mat_copy.a;
create( src->height, src->width, src->type );
cvCopy( src, this );
}
CvMAT::CvMAT( const _CvMAT_CVT_& mat_cvt )
{
type = 0;
data.ptr = 0;
refcount = 0;
*this = mat_cvt;
}
CvMAT::CvMAT( const _CvMAT_DOT_OP_& dot_op )
{
data.ptr = 0;
type = 0;
refcount = 0;
*this = dot_op;
}
CvMAT::CvMAT( const _CvMAT_SOLVE_& solve_mat )
{
type = 0;
data.ptr = 0;
refcount = 0;
*this = solve_mat;
}
CvMAT::CvMAT( const _CvMAT_CMP_& cmp_mat )
{
type = 0;
data.ptr = 0;
refcount = 0;
*this = cmp_mat;
}
/****************************************************************************************\
* CvMAT::operator = *
\****************************************************************************************/
CvMAT& CvMAT::operator = ( const _CvMAT_T_& mat_t )
{
CvMAT* src = (CvMAT*)&mat_t.a;
if( !data.ptr )
{
create( src->width, src->height, src->type );
}
cvTranspose( src, this );
return *this;
}
CvMAT& CvMAT::operator = ( const _CvMAT_ADD_& mat_add )
{
CvMAT* a = mat_add.a;
CvMAT* b = mat_add.b;
if( !data.ptr )
{
create( a->height, a->width, a->type );
}
if( mat_add.beta == 1 )
{
cvAdd( a, b, this );
return *this;
}
if( mat_add.beta == -1 )
{
cvSub( a, b, this );
return *this;
}
if( CV_MAT_DEPTH(a->type) >= CV_32F && CV_MAT_CN(a->type) <= 2 )
cvScaleAdd( b, cvScalar(mat_add.beta), a, this );
else
cvAddWeighted( a, 1, b, mat_add.beta, 0, this );
return *this;
}
CvMAT& CvMAT::operator = ( const _CvMAT_ADD_EX_& mat_add )
{
CvMAT* a = mat_add.a;
CvMAT* b = mat_add.b;
if( !data.ptr )
{
create( a->height, a->width, a->type );
}
cvAddWeighted( a, mat_add.alpha, b, mat_add.beta, mat_add.gamma, this );
return *this;
}
CvMAT& CvMAT::operator = ( const _CvMAT_SCALE_& scale_mat )
{
CvMAT* src = scale_mat.a;
if( !data.ptr )
{
create( src->height, src->width, src->type );
}
cvConvertScale( src, this, scale_mat.alpha, 0 );
return *this;
}
CvMAT& CvMAT::operator = ( const _CvMAT_SCALE_SHIFT_& scale_shift_mat )
{
CvMAT* src = scale_shift_mat.a;
if( !data.ptr )
{
create( src->height, src->width, src->type );
}
cvConvertScale( src, this, scale_shift_mat.alpha, scale_shift_mat.beta );
return *this;
}
CvMAT& CvMAT::operator = ( const _CvMAT_MUL_& mmul )
{
CvMAT* a = mmul.a;
CvMAT* b = mmul.b;
int t_a = mmul.t_ab & 1;
int t_b = (mmul.t_ab & 2) != 0;
int m = (&(a->rows))[t_a];
int n = (&(b->rows))[t_b ^ 1];
/* this(m x n) = (a^o1(t))(m x l) * (b^o2(t))(l x n) */
if( !data.ptr )
{
create( m, n, a->type );
}
if( mmul.alpha == 1 )
{
if( mmul.t_ab == 0 )
{
cvMatMulAdd( a, b, 0, this );
return *this;
}
if( a->data.ptr == b->data.ptr && mmul.t_ab < 3 &&
a->rows == b->rows && a->cols == b->cols &&
a->data.ptr != data.ptr )
{
cvMulTransposed( a, this, mmul.t_ab & 1 );
return *this;
}
}
cvGEMM( a, b, mmul.alpha, 0, 0, this, mmul.t_ab );
return *this;
}
CvMAT& CvMAT::operator = ( const _CvMAT_MUL_ADD_& mmuladd )
{
CvMAT* a = mmuladd.a;
CvMAT* b = mmuladd.b;
CvMAT* c = mmuladd.c;
int t_a = mmuladd.t_abc & 1;
int t_b = (mmuladd.t_abc & 2) != 0;
int m = (&(a->rows))[t_a];
int n = (&(b->rows))[t_b ^ 1];
/* this(m x n) = (a^o1(t))(m x l) * (b^o2(t))(l x n) */
if( !data.ptr )
{
create( m, n, a->type );
}
if( mmuladd.t_abc == 0 && mmuladd.alpha == 1 && mmuladd.beta == 1 )
cvMatMulAdd( a, b, c, this );
else
cvGEMM( a, b, mmuladd.alpha, c, mmuladd.beta, this, mmuladd.t_abc );
return *this;
}
CvMAT& CvMAT::operator = ( const _CvMAT_INV_& inv_mat )
{
CvMAT* src = (CvMAT*)&inv_mat.a;
if( !data.ptr )
{
create( src->height, src->width, src->type );
}
if( inv_mat.method == 0 )
cvInvert( src, this );
else
cvPseudoInv( src, this );
return *this;
}
CvMAT& CvMAT::operator = ( const _CvMAT_NOT_& not_mat )
{
CvMAT* src = not_mat.a;
if( !data.ptr )
{
create( src->height, src->width, src->type );
}
cvNot( src, this );
return *this;
}
CvMAT& CvMAT::operator = ( const _CvMAT_LOGIC_& mat_logic )
{
CvMAT* a = mat_logic.a;
CvMAT* b = mat_logic.b;
int flags = mat_logic.flags;
_CvMAT_LOGIC_::Op op = mat_logic.op;
if( !data.ptr )
{
create( a->height, a->width, a->type );
}
switch( op )
{
case _CvMAT_LOGIC_::AND:
if( flags == 0 )
cvAnd( a, b, this );
else if( flags == 3 )
{
cvOr( a, b, this );
cvNot( this, this );
}
else if( flags == 1 )
{
if( data.ptr == b->data.ptr )
{
cvNot( b, this );
cvOr( this, a, this );
cvNot( this, this );
}
else
{
cvNot( a, this );
cvAnd( this, b, this );
}
}
else
{
if( data.ptr == a->data.ptr )
{
cvNot( a, this );
cvOr( this, b, this );
cvNot( this, this );
}
else
{
cvNot( b, this );
cvAnd( this, a, this );
}
}
break;
case _CvMAT_LOGIC_::OR:
if( flags == 0 )
cvOr( a, b, this );
else if( flags == 3 )
{
cvAnd( a, b, this );
cvNot( this, this );
}
else if( flags == 1 )
{
if( data.ptr == b->data.ptr )
{
cvNot( b, this );
cvAnd( this, a, this );
cvNot( this, this );
}
else
{
cvNot( a, this );
cvOr( this, b, this );
}
}
else
{
if( data.ptr == a->data.ptr )
{
cvNot( a, this );
cvAnd( this, b, this );
cvNot( this, this );
}
else
{
cvNot( b, this );
cvOr( this, a, this );
}
}
break;
case _CvMAT_LOGIC_::XOR:
cvXor( a, b, this );
if( flags == 1 || flags == 2 )
cvNot( this, this );
break;
}
return *this;
}
CvMAT& CvMAT::operator = ( const _CvMAT_UN_LOGIC_& mat_logic )
{
CvMAT* a = mat_logic.a;
CvScalar scalar = cvScalarAll( mat_logic.alpha );
int flags = mat_logic.flags;
_CvMAT_LOGIC_::Op op = mat_logic.op;
if( !data.ptr )
{
create( a->height, a->width, a->type );
}
switch( op )
{
case _CvMAT_LOGIC_::AND:
if( flags == 0 )
cvAndS( a, scalar, this );
else
{
cvNot( a, this );
cvAndS( this, scalar, this );
}
break;
case _CvMAT_LOGIC_::OR:
if( flags == 0 )
cvOrS( a, scalar, this );
else
{
cvNot( a, this );
cvOrS( this, scalar, this );
}
break;
case _CvMAT_LOGIC_::XOR:
if( flags == 0 )
cvXorS( a, scalar, this );
else
cvXorS( a, ~scalar, this );
break;
}
return *this;
}
CvMAT& CvMAT::operator = ( const _CvMAT_COPY_& mat_copy )
{
CvMAT* src = (CvMAT*)mat_copy.a;
if( !data.ptr )
{
create( src->height, src->width, src->type );
}
if( src != this )
cvCopy( src, this );
return *this;
}
CvMAT& CvMAT::operator = ( const _CvMAT_CVT_& mat_cvt )
{
CvMAT* src = (CvMAT*)&mat_cvt.a;
if( !data.ptr )
{
int depth = mat_cvt.newdepth;
create( src->height, src->width, depth < 0 ? src->type :
CV_MAT_CN(src->type)|CV_MAT_DEPTH(depth));
}
cvCvtScale( src, this, mat_cvt.scale, mat_cvt.shift );
return *this;
}
CvMAT& CvMAT::operator = ( const _CvMAT_DOT_OP_& dot_op )
{
CvMAT* a = (CvMAT*)&(dot_op.a);
CvMAT* b = dot_op.b;
if( !data.ptr )
{
create( a->height, a->width, a->type );
}
switch( dot_op.op )
{
case '*':
cvMul( a, b, this, dot_op.alpha );
break;
case '/':
if( b != 0 )
cvDiv( a, b, this, dot_op.alpha );
else
cvDiv( 0, a, this, dot_op.alpha );
break;
case 'm':
if( b != 0 )
cvMin( a, b, this );
else
cvMinS( a, dot_op.alpha, this );
break;
case 'M':
if( b != 0 )
cvMax( a, b, this );
else
cvMaxS( a, dot_op.alpha, this );
break;
case 'a':
if( b != 0 )
cvAbsDiff( a, b, this );
else
cvAbsDiffS( a, this, cvScalar(dot_op.alpha) );
break;
default:
assert(0);
}
return *this;
}
CvMAT& CvMAT::operator = ( const _CvMAT_SOLVE_& solve_mat )
{
CvMAT* a = (CvMAT*)(solve_mat.a);
CvMAT* b = (CvMAT*)(solve_mat.b);
if( !data.ptr )
{
create( a->height, b->width, a->type );
}
if( solve_mat.method == 0 )
cvSolve( a, b, this );
else
{
CvMAT temp;
cvInitMatHeader( &temp, a->cols, a->rows, a->type );
cvCreateData( &temp );
cvPseudoInv( a, &temp );
cvMatMul( &temp, b, this );
}
return *this;
}
CvMAT& CvMAT::operator = ( const _CvMAT_CMP_& mat_cmp )
{
CvMAT* a = mat_cmp.a;
CvMAT* b = mat_cmp.b;
if( !data.ptr )
{
create( a->height, a->width, CV_8UC1 );
}
if( b )
cvCmp( a, b, this, mat_cmp.cmp_op );
else
cvCmpS( a, mat_cmp.alpha, this, mat_cmp.cmp_op );
return *this;
}
/****************************************************************************************\
* CvMAT I/O operations *
\****************************************************************************************/
void CvMAT::write( const char* name, FILE* f, const char* fmt )
{
int i, j, w = width * CV_MAT_CN(type);
FILE* out = f ? f : stdout;
if( name )
fprintf( stdout, "%s(%d x %d) =\n\t", name, rows, cols );
for( i = 0; i < rows; i++ )
{
switch( CV_MAT_DEPTH(type))
{
case CV_8U: if( !fmt )
fmt = "%4d";
for( j = 0; j < w; j++ )
fprintf( out, fmt, ((uchar*)(data.ptr + i*step))[j] );
break;
case CV_8S: if( !fmt )
fmt = "%5d";
for( j = 0; j < w; j++ )
fprintf( out, fmt, ((char*)(data.ptr + i*step))[j] );
break;
case CV_16S: if( !fmt )
fmt = "%7d";
for( j = 0; j < w; j++ )
fprintf( out, fmt, ((short*)(data.ptr + i*step))[j] );
break;
case CV_32S: if( !fmt )
fmt = " %08x";
for( j = 0; j < w; j++ )
fprintf( out, fmt, ((int*)(data.ptr + i*step))[j] );
break;
case CV_32F: if( !fmt )
fmt = "%15g";
for( j = 0; j < w; j++ )
fprintf( out, fmt, ((float*)(data.ptr + i*step))[j] );
break;
case CV_64F: if( !fmt )
fmt = "%15g";
for( j = 0; j < w; j++ )
fprintf( out, fmt, ((double*)(data.ptr + i*step))[j] );
break;
}
fprintf( out, "\n%s", i < rows - 1 ? "\t" : "" );
}
fprintf( out, "\n" );
}
#endif /* _MSC_VER || __BORLANDC__ */
/* End of file. */

View File

@@ -0,0 +1,855 @@
/*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"
#define PATH_TO_E 1
#define PATH_TO_SE 2
#define PATH_TO_S 3
#define K_S 2
#define E_S 2
#define C_S .01
#define K_Z 5000
#define K_NM 50000
#define K_B 40
#define NULL_EDGE 0.001f
#define inf DBL_MAX
typedef struct __CvWork
{
double w_east;
double w_southeast;
double w_south;
char path_e;
char path_se;
char path_s;
}_CvWork;
double _cvBendingWork( CvPoint2D32f* B0,
CvPoint2D32f* F0,
CvPoint2D32f* B1,
CvPoint2D32f* F1/*,
CvPoint* K */);
double _cvStretchingWork(CvPoint2D32f* P1,
CvPoint2D32f* P2);
void _cvWorkEast (int i, int j, _CvWork** W, CvPoint2D32f* edges1, CvPoint2D32f* edges2);
void _cvWorkSouthEast(int i, int j, _CvWork** W, CvPoint2D32f* edges1, CvPoint2D32f* edges2);
void _cvWorkSouth (int i, int j, _CvWork** W, CvPoint2D32f* edges1, CvPoint2D32f* edges2);
static CvPoint2D32f null_edge = {0,0};
double _cvStretchingWork(CvPoint2D32f* P1,
CvPoint2D32f* P2)
{
double L1,L2, L_min, dL;
L1 = sqrt( (double)P1->x*P1->x + P1->y*P1->y);
L2 = sqrt( (double)P2->x*P2->x + P2->y*P2->y);
L_min = MIN(L1, L2);
dL = fabs( L1 - L2 );
return K_S * pow( dL, E_S ) / ( L_min + C_S*dL );
}
////////////////////////////////////////////////////////////////////////////////////
double _cvBendingWork( CvPoint2D32f* B0,
CvPoint2D32f* F0,
CvPoint2D32f* B1,
CvPoint2D32f* F1/*,
CvPoint* K*/)
{
CvPoint2D32f Q( CvPoint2D32f q0, CvPoint2D32f q1, CvPoint2D32f q2, double t );
double angle( CvPoint2D32f A, CvPoint2D32f B );
CvPoint2D32f Q0, Q1, Q2;
CvPoint2D32f Q1_nm = { 0, 0 }, Q2_nm = { 0, 0 };
double d0, d1, d2, des, t_zero;
double k_zero, k_nonmon;
CvPoint2D32f center;
double check01, check02;
char check_origin;
double d_angle, d_nm_angle;
/*
if( (B0->x==0) && (B0->y==0) )
{
if( (F0->x==0) && (F0->y==0) )
{
B1->x = -B1->x;
B1->y = -B1->y;
d_angle = acos( (B1->x*F1->x + B1->y*F1->y)/sqrt( (B1->x*B1->x + B1->y*B1->y)*(F1->x*F1->x + F1->y*F1->y) ) );
d_angle = CV_PI - d_angle;
B1->x = -B1->x;
B1->y = -B1->y;
//return d_angle*K_B;
return 100;
}
K->x = -K->x;
K->y = -K->y;
B1->x = -B1->x;
B1->y = -B1->y;
d_angle = acos( (B1->x*F1->x + B1->y*F1->y)/sqrt( (B1->x*B1->x + B1->y*B1->y)*(F1->x*F1->x + F1->y*F1->y) ) );
d_angle = d_angle - acos( (F0->x*K->x + F0->y*K->y)/sqrt( (F0->x*F0->x + F0->y*F0->y)*(K->x*K->x + K->y*K->y) ) );
d_angle = d_angle - CV_PI*0.5;
d_angle = fabs(d_angle);
K->x = -K->x;
K->y = -K->y;
B1->x = -B1->x;
B1->y = -B1->y;
//return d_angle*K_B;
return 100;
}
if( (F0->x==0) && (F0->y==0) )
{
K->x = -K->x;
K->y = -K->y;
B1->x = -B1->x;
B1->y = -B1->y;
d_angle = acos( (B1->x*F1->x + B1->y*F1->y)/sqrt( (B1->x*B1->x + B1->y*B1->y)*(F1->x*F1->x + F1->y*F1->y) ) );
d_angle = d_angle - acos( (B0->x*K->x + B0->y*K->y)/sqrt( (B0->x*B0->x + B0->y*B0->y)*(K->x*K->x + K->y*K->y) ) );
d_angle = d_angle - CV_PI*0.5;
d_angle = fabs(d_angle);
K->x = -K->x;
K->y = -K->y;
B1->x = -B1->x;
B1->y = -B1->y;
//return d_angle*K_B;
return 100;
}
///////////////
if( (B1->x==0) && (B1->y==0) )
{
if( (F1->x==0) && (F1->y==0) )
{
B0->x = -B0->x;
B0->y = -B0->y;
d_angle = acos( (B0->x*F0->x + B0->y*F0->y)/sqrt( (B0->x*B0->x + B0->y*B0->y)*(F0->x*F0->x + F0->y*F0->y) ) );
d_angle = CV_PI - d_angle;
B0->x = -B0->x;
B0->y = -B0->y;
//return d_angle*K_B;
return 100;
}
K->x = -K->x;
K->y = -K->y;
B0->x = -B0->x;
B0->y = -B0->y;
d_angle = acos( (B0->x*F0->x + B0->y*F0->y)/sqrt( (B0->x*B0->x + B0->y*B0->y)*(F0->x*F0->x + F0->y*F0->y) ) );
d_angle = d_angle - acos( (F1->x*K->x + F1->y*K->y)/sqrt( (F1->x*F1->x + F1->y*F1->y)*(K->x*K->x + K->y*K->y) ) );
d_angle = d_angle - CV_PI*0.5;
d_angle = fabs(d_angle);
K->x = -K->x;
K->y = -K->y;
B0->x = -B0->x;
B0->y = -B0->y;
//return d_angle*K_B;
return 100;
}
if( (F1->x==0) && (F1->y==0) )
{
K->x = -K->x;
K->y = -K->y;
B0->x = -B0->x;
B0->y = -B0->y;
d_angle = acos( (B0->x*F0->x + B0->y*F0->y)/sqrt( (B0->x*B0->x + B0->y*B0->y)*(F0->x*F0->x + F0->y*F0->y) ) );
d_angle = d_angle - acos( (B1->x*K->x + B1->y*K->y)/sqrt( (B1->x*B1->x + B1->y*B1->y)*(K->x*K->x + K->y*K->y) ) );
d_angle = d_angle - CV_PI*0.5;
d_angle = fabs(d_angle);
K->x = -K->x;
K->y = -K->y;
B0->x = -B0->x;
B0->y = -B0->y;
//return d_angle*K_B;
return 100;
}
*/
/*
B0->x = -B0->x;
B0->y = -B0->y;
B1->x = -B1->x;
B1->y = -B1->y;
*/
Q0.x = F0->x * (-B0->x) + F0->y * (-B0->y);
Q0.y = F0->x * (-B0->y) - F0->y * (-B0->x);
Q1.x = 0.5f*( (F1->x * (-B0->x) + F1->y * (-B0->y)) + (F0->x * (-B1->x) + F0->y * (-B1->y)) );
Q1.y = 0.5f*( (F1->x * (-B0->y) - F1->y * (-B0->x)) + (F0->x * (-B1->y) - F0->y * (-B1->x)) );
Q2.x = F1->x * (-B1->x) + F1->y * (-B1->y);
Q2.y = F1->x * (-B1->y) - F1->y * (-B1->x);
d0 = Q0.x * Q1.y - Q0.y * Q1.x;
d1 = 0.5f*(Q0.x * Q2.y - Q0.y * Q2.x);
d2 = Q1.x * Q2.y - Q1.y * Q2.x;
// Check angles goes to zero
des = Q1.y*Q1.y - Q0.y*Q2.y;
k_zero = 0;
if( des >= 0 )
{
t_zero = ( Q0.y - Q1.y + sqrt(des) )/( Q0.y - 2*Q1.y + Q2.y );
if( (0 < t_zero) && (t_zero < 1) && ( Q(Q0, Q1, Q2, t_zero).x > 0 ) )
{
k_zero = inf;
}
t_zero = ( Q0.y - Q1.y - sqrt(des) )/( Q0.y - 2*Q1.y + Q2.y );
if( (0 < t_zero) && (t_zero < 1) && ( Q(Q0, Q1, Q2, t_zero).x > 0 ) )
{
k_zero = inf;
}
}
// Check nonmonotonic
des = d1*d1 - d0*d2;
k_nonmon = 0;
if( des >= 0 )
{
t_zero = ( d0 - d1 - sqrt(des) )/( d0 - 2*d1 + d2 );
if( (0 < t_zero) && (t_zero < 1) )
{
k_nonmon = 1;
Q1_nm = Q(Q0, Q1, Q2, t_zero);
}
t_zero = ( d0 - d1 + sqrt(des) )/( d0 - 2*d1 + d2 );
if( (0 < t_zero) && (t_zero < 1) )
{
k_nonmon += 2;
Q2_nm = Q(Q0, Q1, Q2, t_zero);
}
}
// Finde origin lie in Q0Q1Q2
check_origin = 1;
center.x = (Q0.x + Q1.x + Q2.x)/3;
center.y = (Q0.y + Q1.y + Q2.y)/3;
check01 = (center.x - Q0.x)*(Q1.y - Q0.y) + (center.y - Q0.y)*(Q1.x - Q0.x);
check02 = (-Q0.x)*(Q1.y - Q0.y) + (-Q0.y)*(Q1.x - Q0.x);
if( check01*check02 > 0 )
{
check01 = (center.x - Q1.x)*(Q2.y - Q1.y) + (center.y - Q1.y)*(Q2.x - Q1.x);
check02 = (-Q1.x)*(Q2.y - Q1.y) + (-Q1.y)*(Q2.x - Q1.x);
if( check01*check02 > 0 )
{
check01 = (center.x - Q2.x)*(Q0.y - Q2.y) + (center.y - Q2.y)*(Q0.x - Q2.x);
check02 = (-Q2.x)*(Q0.y - Q2.y) + (-Q2.y)*(Q0.x - Q2.x);
if( check01*check02 > 0 )
{
check_origin = 0;
}
}
}
// Calculate angle
d_nm_angle = 0;
d_angle = angle(Q0,Q2);
if( k_nonmon == 0 )
{
if( check_origin == 0 )
{
}
else
{
d_angle = 2*CV_PI - d_angle;
}
}
else
{
if( k_nonmon == 1 )
{
d_nm_angle = angle(Q0,Q1_nm);
if(d_nm_angle > d_angle)
{
d_nm_angle = d_nm_angle - d_angle;
}
}
if( k_nonmon == 2 )
{
d_nm_angle = angle(Q0,Q2_nm);
if(d_nm_angle > d_angle)
{
d_nm_angle = d_nm_angle - d_angle;
}
}
if( k_nonmon == 3 )
{
d_nm_angle = angle(Q0,Q1_nm);
if(d_nm_angle > d_angle)
{
d_nm_angle = d_nm_angle - d_angle;
d_nm_angle = d_nm_angle + angle(Q0, Q2_nm);
}
else
{
d_nm_angle = d_nm_angle + angle(Q2,Q2_nm);
}
}
}
/*
B0->x = -B0->x;
B0->y = -B0->y;
B1->x = -B1->x;
B1->y = -B1->y;
*/
return d_angle*K_B + d_nm_angle*K_NM + k_zero*K_Z;
//return 0;
}
/////////////////////////////////////////////////////////////////////////////////
void _cvWorkEast(int i, int j, _CvWork** W, CvPoint2D32f* edges1, CvPoint2D32f* edges2)
{
double w1,w2;
CvPoint2D32f small_edge;
//W[i,j].w_east
w1 = W[i-1][j].w_east /*+ _cvBendingWork( &edges1[i-2],
&edges1[i-1],
&null_edge ,
&null_edge,
NULL)*/;
small_edge.x = NULL_EDGE*edges1[i-1].x;
small_edge.y = NULL_EDGE*edges1[i-1].y;
w2 = W[i-1][j].w_southeast + _cvBendingWork(&edges1[i-2],
&edges1[i-1],
&edges2[j-1],
/*&null_edge*/&small_edge/*,
&edges2[j]*/);
if(w1<w2)
{
W[i][j].w_east = w1 + _cvStretchingWork( &edges1[i-1], &null_edge );
W[i][j].path_e = PATH_TO_E;
}
else
{
W[i][j].w_east = w2 + _cvStretchingWork( &edges1[i-1], &null_edge );
W[i][j].path_e = PATH_TO_SE;
}
}
////////////////////////////////////////////////////////////////////////////////////
void _cvWorkSouthEast(int i, int j, _CvWork** W, CvPoint2D32f* edges1, CvPoint2D32f* edges2)
{
double w1,w2,w3;
CvPoint2D32f small_edge;
//W[i,j].w_southeast
small_edge.x = NULL_EDGE*edges1[i-2].x;
small_edge.y = NULL_EDGE*edges1[i-2].y;
w1 = W[i-1][j-1].w_east + _cvBendingWork(&edges1[i-2],
&edges1[i-1],
/*&null_edge*/&small_edge,
&edges2[j-1]/*,
&edges2[j-2]*/);
w2 = W[i-1][j-1].w_southeast + _cvBendingWork( &edges1[i-2],
&edges1[i-1],
&edges2[j-2],
&edges2[j-1]/*,
NULL*/);
small_edge.x = NULL_EDGE*edges2[j-2].x;
small_edge.y = NULL_EDGE*edges2[j-2].y;
w3 = W[i-1][j-1].w_south + _cvBendingWork( /*&null_edge*/&small_edge,
&edges1[i-1],
&edges2[j-2],
&edges2[j-1]/*,
&edges1[i-2]*/);
if( w1<w2 )
{
if(w1<w3)
{
W[i][j].w_southeast = w1 + _cvStretchingWork( &edges1[i-1], &edges2[j-1] );
W[i][j].path_se = PATH_TO_E;
}
else
{
W[i][j].w_southeast = w3 + _cvStretchingWork( &edges1[i-1], &edges2[j-1] );
W[i][j].path_se = 3;
}
}
else
{
if( w2<w3)
{
W[i][j].w_southeast = w2 + _cvStretchingWork( &edges1[i-1], &edges2[j-1] );
W[i][j].path_se = PATH_TO_SE;
}
else
{
W[i][j].w_southeast = w3 + _cvStretchingWork( &edges1[i-1], &edges2[j-1] );
W[i][j].path_se = 3;
}
}
}
//////////////////////////////////////////////////////////////////////////////////////
void _cvWorkSouth(int i, int j, _CvWork** W, CvPoint2D32f* edges1, CvPoint2D32f* edges2)
{
double w1,w2;
CvPoint2D32f small_edge;
//W[i,j].w_south
small_edge.x = NULL_EDGE*edges2[j-1].x;
small_edge.y = NULL_EDGE*edges2[j-1].y;
w1 = W[i][j-1].w_southeast + _cvBendingWork(&edges1[i-1],
/*&null_edge*/&small_edge,
&edges2[j-2],
&edges2[j-1]/*,
&edges1[i]*/);
w2 = W[i][j-1].w_south /*+ _cvBendingWork( &null_edge ,
&null_edge,
&edges2[j-2],
&edges2[j-1],
NULL)*/;
if( w1<w2 )
{
W[i][j].w_south = w1 + _cvStretchingWork( &null_edge, &edges2[j-1] );
W[i][j].path_s = PATH_TO_SE;
}
else
{
W[i][j].w_south = w2 + _cvStretchingWork( &null_edge, &edges2[j-1] );
W[i][j].path_s = 3;
}
}
//===================================================
CvPoint2D32f Q(CvPoint2D32f q0,CvPoint2D32f q1,CvPoint2D32f q2,double t)
{
CvPoint2D32f q;
q.x = (float)(q0.x*(1-t)*(1-t) + 2*q1.x*t*(1-t) + q2.x*t*t);
q.y = (float)(q0.y*(1-t)*(1-t) + 2*q1.y*t*(1-t) + q2.y*t*t);
return q;
}
double angle(CvPoint2D32f A, CvPoint2D32f B)
{
return acos( (A.x*B.x + A.y*B.y)/sqrt( (double)(A.x*A.x + A.y*A.y)*(B.x*B.x + B.y*B.y) ) );
}
/***************************************************************************************\
*
* This function compute intermediate polygon between contour1 and contour2
*
* Correspondence between points of contours specify by corr
*
* param = [0,1]; 0 correspondence to contour1, 1 - contour2
*
\***************************************************************************************/
CvSeq* icvBlendContours(CvSeq* contour1,
CvSeq* contour2,
CvSeq* corr,
double param,
CvMemStorage* storage)
{
int j;
CvSeqWriter writer01;
CvSeqReader reader01;
int Ni,Nj; // size of contours
int i; // counter
CvPoint* point1; // array of first contour point
CvPoint* point2; // array of second contour point
CvPoint point_output; // intermediate storage of ouput point
int corr_point;
// Create output sequence.
CvSeq* output = cvCreateSeq(0,
sizeof(CvSeq),
sizeof(CvPoint),
storage );
// Find size of contours.
Ni = contour1->total + 1;
Nj = contour2->total + 1;
point1 = (CvPoint* )malloc( Ni*sizeof(CvPoint) );
point2 = (CvPoint* )malloc( Nj*sizeof(CvPoint) );
// Initialize arrays of point
cvCvtSeqToArray( contour1, point1, CV_WHOLE_SEQ );
cvCvtSeqToArray( contour2, point2, CV_WHOLE_SEQ );
// First and last point mast be equal.
point1[Ni-1] = point1[0];
point2[Nj-1] = point2[0];
// Initializes process of writing to sequence.
cvStartAppendToSeq( output, &writer01);
i = Ni-1; //correspondence to points of contour1
for( ; corr; corr = corr->h_next )
{
//Initializes process of sequential reading from sequence
cvStartReadSeq( corr, &reader01, 0 );
for(j=0; j < corr->total; j++)
{
// Read element from sequence.
CV_READ_SEQ_ELEM( corr_point, reader01 );
// Compute point of intermediate polygon.
point_output.x = cvRound(point1[i].x + param*( point2[corr_point].x - point1[i].x ));
point_output.y = cvRound(point1[i].y + param*( point2[corr_point].y - point1[i].y ));
// Write element to sequence.
CV_WRITE_SEQ_ELEM( point_output, writer01 );
}
i--;
}
// Updates sequence header.
cvFlushSeqWriter( &writer01 );
return output;
}
/**************************************************************************************************
*
*
*
*
*
*
*
*
*
*
**************************************************************************************************/
void icvCalcContoursCorrespondence(CvSeq* contour1,
CvSeq* contour2,
CvSeq** corr,
CvMemStorage* storage)
{
int i,j; // counter of cycles
int Ni,Nj; // size of contours
_CvWork** W; // graph for search minimum of work
CvPoint* point1; // array of first contour point
CvPoint* point2; // array of second contour point
CvPoint2D32f* edges1; // array of first contour edge
CvPoint2D32f* edges2; // array of second contour edge
//CvPoint null_edge = {0,0}; //
CvPoint2D32f small_edge;
//double inf; // infinity
CvSeq* corr01;
CvSeqWriter writer;
char path; //
// Find size of contours
Ni = contour1->total + 1;
Nj = contour2->total + 1;
// Create arrays
W = (_CvWork**)malloc(sizeof(_CvWork*)*Ni);
for(i=0; i<Ni; i++)
{
W[i] = (_CvWork*)malloc(sizeof(_CvWork)*Nj);
}
point1 = (CvPoint* )malloc( Ni*sizeof(CvPoint) );
point2 = (CvPoint* )malloc( Nj*sizeof(CvPoint) );
edges1 = (CvPoint2D32f* )malloc( (Ni-1)*sizeof(CvPoint2D32f) );
edges2 = (CvPoint2D32f* )malloc( (Nj-1)*sizeof(CvPoint2D32f) );
// Initialize arrays of point
cvCvtSeqToArray( contour1, point1, CV_WHOLE_SEQ );
cvCvtSeqToArray( contour2, point2, CV_WHOLE_SEQ );
point1[Ni-1] = point1[0];
point2[Nj-1] = point2[0];
for(i=0;i<Ni-1;i++)
{
edges1[i].x = (float)( point1[i+1].x - point1[i].x );
edges1[i].y = (float)( point1[i+1].y - point1[i].y );
};
for(i=0;i<Nj-1;i++)
{
edges2[i].x = (float)( point2[i+1].x - point2[i].x );
edges2[i].y = (float)( point2[i+1].y - point2[i].y );
};
// Find infinity constant
//inf=1;
/////////////
//Find min path in graph
/////////////
W[0][0].w_east = 0;
W[0][0].w_south = 0;
W[0][0].w_southeast = 0;
W[1][1].w_southeast = _cvStretchingWork( &edges1[0], &edges2[0] );
W[1][1].w_east = inf;
W[1][1].w_south = inf;
W[1][1].path_se = PATH_TO_SE;
W[0][1].w_south = _cvStretchingWork( &null_edge, &edges2[0] );
W[0][1].path_s = 3;
W[1][0].w_east = _cvStretchingWork( &edges2[0], &null_edge );
W[1][0].path_e = PATH_TO_E;
for( i=1; i<Ni; i++ )
{
W[i][0].w_south = inf;
W[i][0].w_southeast = inf;
}
for(j=1; j<Nj; j++)
{
W[0][j].w_east = inf;
W[0][j].w_southeast = inf;
}
for(i=2; i<Ni; i++)
{
j=0;/////////
W[i][j].w_east = W[i-1][j].w_east;
W[i][j].w_east = W[i][j].w_east /*+
_cvBendingWork( &edges1[i-2], &edges1[i-1], &null_edge, &null_edge, NULL )*/;
W[i][j].w_east = W[i][j].w_east + _cvStretchingWork( &edges2[i-1], &null_edge );
W[i][j].path_e = PATH_TO_E;
j=1;//////////
W[i][j].w_south = inf;
_cvWorkEast (i, j, W, edges1, edges2);
W[i][j].w_southeast = W[i-1][j-1].w_east;
W[i][j].w_southeast = W[i][j].w_southeast + _cvStretchingWork( &edges1[i-1], &edges2[j-1] );
small_edge.x = NULL_EDGE*edges1[i-2].x;
small_edge.y = NULL_EDGE*edges1[i-2].y;
W[i][j].w_southeast = W[i][j].w_southeast +
_cvBendingWork( &edges1[i-2], &edges1[i-1], /*&null_edge*/&small_edge, &edges2[j-1]/*, &edges2[Nj-2]*/);
W[i][j].path_se = PATH_TO_E;
}
for(j=2; j<Nj; j++)
{
i=0;//////////
W[i][j].w_south = W[i][j-1].w_south;
W[i][j].w_south = W[i][j].w_south + _cvStretchingWork( &null_edge, &edges2[j-1] );
W[i][j].w_south = W[i][j].w_south /*+
_cvBendingWork( &null_edge, &null_edge, &edges2[j-2], &edges2[j-1], NULL )*/;
W[i][j].path_s = 3;
i=1;///////////
W[i][j].w_east= inf;
_cvWorkSouth(i, j, W, edges1, edges2);
W[i][j].w_southeast = W[i-1][j-1].w_south;
W[i][j].w_southeast = W[i][j].w_southeast + _cvStretchingWork( &edges1[i-1], &edges2[j-1] );
small_edge.x = NULL_EDGE*edges2[j-2].x;
small_edge.y = NULL_EDGE*edges2[j-2].y;
W[i][j].w_southeast = W[i][j].w_southeast +
_cvBendingWork( /*&null_edge*/&small_edge, &edges1[i-1], &edges2[j-2], &edges2[j-1]/*, &edges1[Ni-2]*/);
W[i][j].path_se = 3;
}
for(i=2; i<Ni; i++)
for(j=2; j<Nj; j++)
{
_cvWorkEast (i, j, W, edges1, edges2);
_cvWorkSouthEast(i, j, W, edges1, edges2);
_cvWorkSouth (i, j, W, edges1, edges2);
}
i=Ni-1;j=Nj-1;
*corr = cvCreateSeq(0,
sizeof(CvSeq),
sizeof(int),
storage );
corr01 = *corr;
cvStartAppendToSeq( corr01, &writer );
if( W[i][j].w_east > W[i][j].w_southeast )
{
if( W[i][j].w_southeast > W[i][j].w_south )
{
path = 3;
}
else
{
path = PATH_TO_SE;
}
}
else
{
if( W[i][j].w_east < W[i][j].w_south )
{
path = PATH_TO_E;
}
else
{
path = 3;
}
}
do
{
CV_WRITE_SEQ_ELEM( j, writer );
switch( path )
{
case PATH_TO_E:
path = W[i][j].path_e;
i--;
cvFlushSeqWriter( &writer );
corr01->h_next = cvCreateSeq( 0,
sizeof(CvSeq),
sizeof(int),
storage );
corr01 = corr01->h_next;
cvStartAppendToSeq( corr01, &writer );
break;
case PATH_TO_SE:
path = W[i][j].path_se;
j--; i--;
cvFlushSeqWriter( &writer );
corr01->h_next = cvCreateSeq( 0,
sizeof(CvSeq),
sizeof(int),
storage );
corr01 = corr01->h_next;
cvStartAppendToSeq( corr01, &writer );
break;
case 3:
path = W[i][j].path_s;
j--;
break;
}
} while( (i>=0) && (j>=0) );
cvFlushSeqWriter( &writer );
// Free memory
for(i=1;i<Ni;i++)
{
free(W[i]);
}
free(W);
free(point1);
free(point2);
free(edges1);
free(edges2);
}

View File

@@ -0,0 +1,392 @@
/*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 <assert.h>
static CvStatus
icvMorphEpilines8uC3( uchar * first_pix, /* raster epiline from image 1 */
uchar * second_pix, /* raster epiline from image 2 */
uchar * dst_pix, /* raster epiline from dest image */
/* (it's an output parameter) */
float alpha, /* relative position of camera */
int *first, /* first sequence of runs */
int first_runs, /* it's length */
int *second, /* second sequence of runs */
int second_runs, int *first_corr, /* corr data for the 1st seq */
int *second_corr, /* corr data for the 2nd seq */
int dst_len )
{
float alpha1; /* alpha - 1.0 */
int s, s1; /* integer variant of alpha and alpha1 ( 0 <= s,s1 <= 256 ) */
int curr; /* current index in run's array */
float begLine; /* begin of current run */
float endLine; /* end of current run */
float begCorr; /* begin of correspondence destination of run */
float endCorr; /* end of correspondence destination of run */
int begDestLine; /* begin of current destanation of run */
int endDestLine; /* end of current destanation of run */
int begLineIndex;
int endLineIndex;
int indexImg1;
float step = 0;
int n;
memset( dst_pix, 0, dst_len );
alpha1 = (float) (1.0 - alpha);
s = (int) (alpha * 256);
s1 = 256 - s;
/* --------------Create first line------------- */
begLineIndex = first[0];
begLine = (float) begLineIndex;
curr = 0;
for( n = 0; n < first_runs; n++ )
{ /* for each run */
begCorr = (float) first_corr[curr];
curr++;
endCorr = (float) first_corr[curr];
curr++;
endLineIndex = first[curr];
endLine = (float) endLineIndex;
begDestLine = (int) (alpha * begLine + alpha1 * begCorr);
endDestLine = (int) (alpha * endLine + alpha1 * endCorr);
indexImg1 = begDestLine * 3;
step = 0;
if( endDestLine != begDestLine )
step = (endLine - begLine) / ((float) (endDestLine - begDestLine));
if( begCorr != endCorr )
{
for( ; begDestLine < endDestLine; begDestLine++ )
{
/* for each pixel */
begLineIndex = (int) begLine;
begLineIndex *= 3;
/* Blend R */
dst_pix[indexImg1] = (uchar) (((int) (first_pix[begLineIndex]) * s) >> 8);
indexImg1++;
/* Blend G */
dst_pix[indexImg1] = (uchar) (((int) (first_pix[begLineIndex + 1]) * s) >> 8);
indexImg1++;
/* Blend B */
dst_pix[indexImg1] = (uchar) (((int) (first_pix[begLineIndex + 2]) * s) >> 8);
indexImg1++;
begLine += step;
} /* for */
}
else
{
for( ; begDestLine < endDestLine; begDestLine++ )
{
/* for each pixel */
begLineIndex = (int) begLine;
begLineIndex *= 3;
/* Blend R */
dst_pix[indexImg1] = first_pix[begLineIndex];
indexImg1++;
/* Blend G */
dst_pix[indexImg1] = first_pix[begLineIndex + 1];
indexImg1++;
/* Blend B */
dst_pix[indexImg1] = first_pix[begLineIndex + 2];
indexImg1++;
begLine += step;
} /* for */
} /* if */
begLineIndex = endLineIndex;
begLine = endLine;
} /* for each runs in first line */
begLineIndex = second[0];
begLine = (float) begLineIndex;
curr = 0;
/* --------------Create second line------------- */
curr = 0;;
for( n = 0; n < second_runs; n++ )
{ /* for each run */
begCorr = (float) second_corr[curr];
curr++;
endCorr = (float) second_corr[curr];
curr++;
endLineIndex = second[curr];
endLine = (float) endLineIndex;
begDestLine = (int) (alpha1 * begLine + alpha * begCorr);
endDestLine = (int) (alpha1 * endLine + alpha * endCorr);
indexImg1 = begDestLine * 3;
step = 0;
if (endDestLine != begDestLine)
step = (endLine - begLine) / ((float) (endDestLine - begDestLine));
if( begCorr != endCorr )
{
for( ; begDestLine < endDestLine; begDestLine++ )
{
/* for each pixel */
begLineIndex = (int) begLine;
begLineIndex *= 3;
/* Blend R */
dst_pix[indexImg1] =
(uchar) (dst_pix[indexImg1] +
(uchar) (((unsigned int) (second_pix[begLineIndex]) * s1) >> 8));
indexImg1++;
/* Blend G */
dst_pix[indexImg1] =
(uchar) (dst_pix[indexImg1] +
(uchar) (((unsigned int) (second_pix[begLineIndex + 1]) * s1) >>
8));
indexImg1++;
/* Blend B */
dst_pix[indexImg1] =
(uchar) (dst_pix[indexImg1] +
(uchar) (((unsigned int) (second_pix[begLineIndex + 2]) * s1) >>
8));
indexImg1++;
begLine += step;
} /* for */
}
else
{
for( ; begDestLine < endDestLine; begDestLine++ )
{
/* for each pixel */
begLineIndex = (int) begLine;
begLineIndex *= 3;
/* Blend R */
dst_pix[indexImg1] = (uchar) (dst_pix[indexImg1] + second_pix[begLineIndex]);
indexImg1++;
/* Blend G */
dst_pix[indexImg1] =
(uchar) (dst_pix[indexImg1] + second_pix[begLineIndex + 1]);
indexImg1++;
/* Blend B */
dst_pix[indexImg1] =
(uchar) (dst_pix[indexImg1] + second_pix[begLineIndex + 2]);
/*assert(indexImg1 < dst_len); */
indexImg1++;
begLine += step;
} /* for */
} /* if */
begLineIndex = endLineIndex;
begLine = endLine;
} /* for each runs in second line */
return CV_NO_ERR;
} /* icvMorphEpilines8uC3 */
/*======================================================================================*/
static CvStatus
icvMorphEpilines8uC3Multi( int lines, /* number of lines */
uchar * first_pix, /* raster epilines from the first image */
int *first_num, /* numbers of pixel in first line */
uchar * second_pix, /* raster epilines from the second image */
int *second_num, /* numbers of pixel in second line */
uchar * dst_pix, /* raster epiline from the destination image */
/* (it's an output parameter) */
int *dst_num, /* numbers of pixel in output line */
float alpha, /* relative position of camera */
int *first, /* first sequence of runs */
int *first_runs, /* it's length */
int *second, /* second sequence of runs */
int *second_runs, int *first_corr, /* correspond information for the 1st seq */
int *second_corr ) /* correspond information for the 2nd seq */
{
CvStatus error;
int currLine;
int currFirstPix = 0;
//int currFirstNum = 0;
int currSecondPix = 0;
//int currSecondNum = 0;
int currDstPix = 0;
int currFirst = 0;
//int currFirstRuns = 0;
int currSecond = 0;
//int currSecondRuns = 0;
int currFirstCorr = 0;
int currSecondCorr = 0;
if( lines < 1 ||
first_pix == 0 ||
first_num == 0 ||
second_pix == 0 ||
second_num == 0 ||
dst_pix == 0 ||
dst_num == 0 ||
alpha < 0 ||
alpha > 1 ||
first == 0 ||
first_runs == 0 ||
second == 0 || second_runs == 0 || first_corr == 0 || second_corr == 0 )
return CV_BADFACTOR_ERR;
for( currLine = 0; currLine < lines; currLine++ )
{
error = icvMorphEpilines8uC3( &(first_pix[currFirstPix]),
&(second_pix[currSecondPix]),
&(dst_pix[currDstPix]),
alpha,
&(first[currFirst]),
first_runs[currLine],
&(second[currSecond]),
second_runs[currLine],
&(first_corr[currFirstCorr]),
&(second_corr[currSecondCorr]), dst_num[currLine] * 3 );
if( error != CV_NO_ERR )
return CV_NO_ERR;
currFirstPix += first_num[currLine] * 3;
currSecondPix += second_num[currLine] * 3;
currDstPix += dst_num[currLine] * 3;
currFirst += (first_runs[currLine] * 2) + 1;
currSecond += (second_runs[currLine] * 2) + 1;
currFirstCorr += first_runs[currLine] * 2;
currSecondCorr += second_runs[currLine] * 2;
} /* for */
return CV_NO_ERR;
} /* icvMorphEpilines8uC3Multi */
/*======================================================================================*/
CV_IMPL void
cvMorphEpilinesMulti( int lines, /* number of lines */
uchar * first_pix, /* raster epilines from the first image */
int *first_num, /* numbers of pixel in first line */
uchar * second_pix, /* raster epilines from the second image */
int *second_num, /* numbers of pixel in second line */
uchar * dst_pix, /* raster epiline from the destination image */
/* (it's an output parameter) */
int *dst_num, /* numbers of pixel in output line */
float alpha, /* relative position of camera */
int *first, /* first sequence of runs */
int *first_runs, /* it's length */
int *second, /* second sequence of runs */
int *second_runs, int *first_corr, /* correspond information for the 1st seq */
int *second_corr /* correspond information for the 2nd seq */
)
{
IPPI_CALL( icvMorphEpilines8uC3Multi( lines, /* number of lines */
first_pix, /* raster epilines from the first image */
first_num, /* numbers of pixel in first line */
second_pix, /* raster epilines from the second image */
second_num, /* numbers of pixel in second line */
dst_pix, /* raster epiline from the destination image */
/* (it's an output parameter) */
dst_num, /* numbers of pixel in output line */
alpha, /* relative position of camera */
first, /* first sequence of runs */
first_runs, /* it's length */
second, /* second sequence of runs */
second_runs, first_corr, /* correspond information for the 1st seq */
second_corr /* correspond information for the 2nd seq */
));
}

357
modules/legacy/src/pgh.cpp Normal file
View File

@@ -0,0 +1,357 @@
/*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"
#define _CV_ACOS_TABLE_SIZE 513
static const float icv_acos_table[_CV_ACOS_TABLE_SIZE] = {
3.14159265f, 3.05317551f, 3.01651113f, 2.98834964f, 2.96458497f, 2.94362719f,
2.92466119f, 2.90720289f, 2.89093699f, 2.87564455f, 2.86116621f, 2.84738169f,
2.83419760f, 2.82153967f, 2.80934770f, 2.79757211f, 2.78617145f, 2.77511069f,
2.76435988f, 2.75389319f, 2.74368816f, 2.73372510f, 2.72398665f, 2.71445741f,
2.70512362f, 2.69597298f, 2.68699438f, 2.67817778f, 2.66951407f, 2.66099493f,
2.65261279f, 2.64436066f, 2.63623214f, 2.62822133f, 2.62032277f, 2.61253138f,
2.60484248f, 2.59725167f, 2.58975488f, 2.58234828f, 2.57502832f, 2.56779164f,
2.56063509f, 2.55355572f, 2.54655073f, 2.53961750f, 2.53275354f, 2.52595650f,
2.51922417f, 2.51255441f, 2.50594525f, 2.49939476f, 2.49290115f, 2.48646269f,
2.48007773f, 2.47374472f, 2.46746215f, 2.46122860f, 2.45504269f, 2.44890314f,
2.44280867f, 2.43675809f, 2.43075025f, 2.42478404f, 2.41885841f, 2.41297232f,
2.40712480f, 2.40131491f, 2.39554173f, 2.38980439f, 2.38410204f, 2.37843388f,
2.37279910f, 2.36719697f, 2.36162673f, 2.35608768f, 2.35057914f, 2.34510044f,
2.33965094f, 2.33423003f, 2.32883709f, 2.32347155f, 2.31813284f, 2.31282041f,
2.30753373f, 2.30227228f, 2.29703556f, 2.29182309f, 2.28663439f, 2.28146900f,
2.27632647f, 2.27120637f, 2.26610827f, 2.26103177f, 2.25597646f, 2.25094195f,
2.24592786f, 2.24093382f, 2.23595946f, 2.23100444f, 2.22606842f, 2.22115104f,
2.21625199f, 2.21137096f, 2.20650761f, 2.20166166f, 2.19683280f, 2.19202074f,
2.18722520f, 2.18244590f, 2.17768257f, 2.17293493f, 2.16820274f, 2.16348574f,
2.15878367f, 2.15409630f, 2.14942338f, 2.14476468f, 2.14011997f, 2.13548903f,
2.13087163f, 2.12626757f, 2.12167662f, 2.11709859f, 2.11253326f, 2.10798044f,
2.10343994f, 2.09891156f, 2.09439510f, 2.08989040f, 2.08539725f, 2.08091550f,
2.07644495f, 2.07198545f, 2.06753681f, 2.06309887f, 2.05867147f, 2.05425445f,
2.04984765f, 2.04545092f, 2.04106409f, 2.03668703f, 2.03231957f, 2.02796159f,
2.02361292f, 2.01927344f, 2.01494300f, 2.01062146f, 2.00630870f, 2.00200457f,
1.99770895f, 1.99342171f, 1.98914271f, 1.98487185f, 1.98060898f, 1.97635399f,
1.97210676f, 1.96786718f, 1.96363511f, 1.95941046f, 1.95519310f, 1.95098292f,
1.94677982f, 1.94258368f, 1.93839439f, 1.93421185f, 1.93003595f, 1.92586659f,
1.92170367f, 1.91754708f, 1.91339673f, 1.90925250f, 1.90511432f, 1.90098208f,
1.89685568f, 1.89273503f, 1.88862003f, 1.88451060f, 1.88040664f, 1.87630806f,
1.87221477f, 1.86812668f, 1.86404371f, 1.85996577f, 1.85589277f, 1.85182462f,
1.84776125f, 1.84370256f, 1.83964848f, 1.83559892f, 1.83155381f, 1.82751305f,
1.82347658f, 1.81944431f, 1.81541617f, 1.81139207f, 1.80737194f, 1.80335570f,
1.79934328f, 1.79533460f, 1.79132959f, 1.78732817f, 1.78333027f, 1.77933581f,
1.77534473f, 1.77135695f, 1.76737240f, 1.76339101f, 1.75941271f, 1.75543743f,
1.75146510f, 1.74749565f, 1.74352900f, 1.73956511f, 1.73560389f, 1.73164527f,
1.72768920f, 1.72373560f, 1.71978441f, 1.71583556f, 1.71188899f, 1.70794462f,
1.70400241f, 1.70006228f, 1.69612416f, 1.69218799f, 1.68825372f, 1.68432127f,
1.68039058f, 1.67646160f, 1.67253424f, 1.66860847f, 1.66468420f, 1.66076139f,
1.65683996f, 1.65291986f, 1.64900102f, 1.64508338f, 1.64116689f, 1.63725148f,
1.63333709f, 1.62942366f, 1.62551112f, 1.62159943f, 1.61768851f, 1.61377831f,
1.60986877f, 1.60595982f, 1.60205142f, 1.59814349f, 1.59423597f, 1.59032882f,
1.58642196f, 1.58251535f, 1.57860891f, 1.57470259f, 1.57079633f, 1.56689007f,
1.56298375f, 1.55907731f, 1.55517069f, 1.55126383f, 1.54735668f, 1.54344917f,
1.53954124f, 1.53563283f, 1.53172389f, 1.52781434f, 1.52390414f, 1.51999323f,
1.51608153f, 1.51216900f, 1.50825556f, 1.50434117f, 1.50042576f, 1.49650927f,
1.49259163f, 1.48867280f, 1.48475270f, 1.48083127f, 1.47690845f, 1.47298419f,
1.46905841f, 1.46513106f, 1.46120207f, 1.45727138f, 1.45333893f, 1.44940466f,
1.44546850f, 1.44153038f, 1.43759024f, 1.43364803f, 1.42970367f, 1.42575709f,
1.42180825f, 1.41785705f, 1.41390346f, 1.40994738f, 1.40598877f, 1.40202755f,
1.39806365f, 1.39409701f, 1.39012756f, 1.38615522f, 1.38217994f, 1.37820164f,
1.37422025f, 1.37023570f, 1.36624792f, 1.36225684f, 1.35826239f, 1.35426449f,
1.35026307f, 1.34625805f, 1.34224937f, 1.33823695f, 1.33422072f, 1.33020059f,
1.32617649f, 1.32214834f, 1.31811607f, 1.31407960f, 1.31003885f, 1.30599373f,
1.30194417f, 1.29789009f, 1.29383141f, 1.28976803f, 1.28569989f, 1.28162688f,
1.27754894f, 1.27346597f, 1.26937788f, 1.26528459f, 1.26118602f, 1.25708205f,
1.25297262f, 1.24885763f, 1.24473698f, 1.24061058f, 1.23647833f, 1.23234015f,
1.22819593f, 1.22404557f, 1.21988898f, 1.21572606f, 1.21155670f, 1.20738080f,
1.20319826f, 1.19900898f, 1.19481283f, 1.19060973f, 1.18639955f, 1.18218219f,
1.17795754f, 1.17372548f, 1.16948589f, 1.16523866f, 1.16098368f, 1.15672081f,
1.15244994f, 1.14817095f, 1.14388370f, 1.13958808f, 1.13528396f, 1.13097119f,
1.12664966f, 1.12231921f, 1.11797973f, 1.11363107f, 1.10927308f, 1.10490563f,
1.10052856f, 1.09614174f, 1.09174500f, 1.08733820f, 1.08292118f, 1.07849378f,
1.07405585f, 1.06960721f, 1.06514770f, 1.06067715f, 1.05619540f, 1.05170226f,
1.04719755f, 1.04268110f, 1.03815271f, 1.03361221f, 1.02905939f, 1.02449407f,
1.01991603f, 1.01532509f, 1.01072102f, 1.00610363f, 1.00147268f, 0.99682798f,
0.99216928f, 0.98749636f, 0.98280898f, 0.97810691f, 0.97338991f, 0.96865772f,
0.96391009f, 0.95914675f, 0.95436745f, 0.94957191f, 0.94475985f, 0.93993099f,
0.93508504f, 0.93022170f, 0.92534066f, 0.92044161f, 0.91552424f, 0.91058821f,
0.90563319f, 0.90065884f, 0.89566479f, 0.89065070f, 0.88561619f, 0.88056088f,
0.87548438f, 0.87038629f, 0.86526619f, 0.86012366f, 0.85495827f, 0.84976956f,
0.84455709f, 0.83932037f, 0.83405893f, 0.82877225f, 0.82345981f, 0.81812110f,
0.81275556f, 0.80736262f, 0.80194171f, 0.79649221f, 0.79101352f, 0.78550497f,
0.77996593f, 0.77439569f, 0.76879355f, 0.76315878f, 0.75749061f, 0.75178826f,
0.74605092f, 0.74027775f, 0.73446785f, 0.72862033f, 0.72273425f, 0.71680861f,
0.71084240f, 0.70483456f, 0.69878398f, 0.69268952f, 0.68654996f, 0.68036406f,
0.67413051f, 0.66784794f, 0.66151492f, 0.65512997f, 0.64869151f, 0.64219789f,
0.63564741f, 0.62903824f, 0.62236849f, 0.61563615f, 0.60883911f, 0.60197515f,
0.59504192f, 0.58803694f, 0.58095756f, 0.57380101f, 0.56656433f, 0.55924437f,
0.55183778f, 0.54434099f, 0.53675018f, 0.52906127f, 0.52126988f, 0.51337132f,
0.50536051f, 0.49723200f, 0.48897987f, 0.48059772f, 0.47207859f, 0.46341487f,
0.45459827f, 0.44561967f, 0.43646903f, 0.42713525f, 0.41760600f, 0.40786755f,
0.39790449f, 0.38769946f, 0.37723277f, 0.36648196f, 0.35542120f, 0.34402054f,
0.33224495f, 0.32005298f, 0.30739505f, 0.29421096f, 0.28042645f, 0.26594810f,
0.25065566f, 0.23438976f, 0.21693146f, 0.19796546f, 0.17700769f, 0.15324301f,
0.12508152f, 0.08841715f, 0.00000000f
};
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: icvCalcPGH
// Purpose:
// Calculates PGH(pairwise geometric histogram) for contour given.
// Context:
// Parameters:
// contour - pointer to input contour object.
// pgh - output histogram
// ang_dim - number of angle bins (vertical size of histogram)
// dist_dim - number of distance bins (horizontal size of histogram)
// Returns:
// CV_OK or error code
// Notes:
//F*/
static CvStatus
icvCalcPGH( const CvSeq * contour, float *pgh, int angle_dim, int dist_dim )
{
char local_buffer[(1 << 14) + 32];
float *local_buffer_ptr = (float *)cvAlignPtr(local_buffer,32);
float *buffer = local_buffer_ptr;
double angle_scale = (angle_dim - 0.51) / icv_acos_table[0];
double dist_scale = DBL_EPSILON;
int buffer_size;
int i, count, pass;
int *pghi = (int *) pgh;
int hist_size = angle_dim * dist_dim;
CvSeqReader reader1, reader2; /* external and internal readers */
if( !contour || !pgh )
return CV_NULLPTR_ERR;
if( angle_dim <= 0 || angle_dim > 180 || dist_dim <= 0 )
return CV_BADRANGE_ERR;
if( !CV_IS_SEQ_POINT_SET( contour ))
return CV_BADFLAG_ERR;
memset( pgh, 0, hist_size * sizeof( pgh[0] ));
count = contour->total;
/* allocate buffer for distances */
buffer_size = count * sizeof( float );
if( buffer_size > (int)sizeof(local_buffer) - 32 )
{
buffer = (float *) cvAlloc( buffer_size );
if( !buffer )
return CV_OUTOFMEM_ERR;
}
cvStartReadSeq( contour, &reader1, 0 );
cvStartReadSeq( contour, &reader2, 0 );
/* calc & store squared edge lengths, calculate maximal distance between edges */
for( i = 0; i < count; i++ )
{
CvPoint pt1, pt2;
double dx, dy;
CV_READ_EDGE( pt1, pt2, reader1 );
dx = pt2.x - pt1.x;
dy = pt2.y - pt1.y;
buffer[i] = (float)(1./sqrt(dx * dx + dy * dy));
}
/*
do 2 passes.
First calculates maximal distance.
Second calculates histogram itself.
*/
for( pass = 1; pass <= 2; pass++ )
{
double dist_coeff = 0, angle_coeff = 0;
/* run external loop */
for( i = 0; i < count; i++ )
{
CvPoint pt1, pt2;
int dx, dy;
int dist = 0;
CV_READ_EDGE( pt1, pt2, reader1 );
dx = pt2.x - pt1.x;
dy = pt2.y - pt1.y;
if( (dx | dy) != 0 )
{
int j;
if( pass == 2 )
{
dist_coeff = buffer[i] * dist_scale;
angle_coeff = buffer[i] * (_CV_ACOS_TABLE_SIZE / 2);
}
/* run internal loop (for current edge) */
for( j = 0; j < count; j++ )
{
CvPoint pt3, pt4;
CV_READ_EDGE( pt3, pt4, reader2 );
if( i != j ) /* process edge pair */
{
int d1 = (pt3.y - pt1.y) * dx - (pt3.x - pt1.x) * dy;
int d2 = (pt4.y - pt1.y) * dx - (pt2.x - pt1.x) * dy;
int cross_flag;
int *hist_row = 0;
if( pass == 2 )
{
int dp = (pt4.x - pt3.x) * dx + (pt4.y - pt3.y) * dy;
dp = cvRound( dp * angle_coeff * buffer[j] ) +
(_CV_ACOS_TABLE_SIZE / 2);
dp = MAX( dp, 0 );
dp = MIN( dp, _CV_ACOS_TABLE_SIZE - 1 );
hist_row = pghi + dist_dim *
cvRound( icv_acos_table[dp] * angle_scale );
d1 = cvRound( d1 * dist_coeff );
d2 = cvRound( d2 * dist_coeff );
}
cross_flag = (d1 ^ d2) < 0;
d1 = CV_IABS( d1 );
d2 = CV_IABS( d2 );
if( pass == 2 )
{
if( d1 >= dist_dim )
d1 = dist_dim - 1;
if( d2 >= dist_dim )
d2 = dist_dim - 1;
if( !cross_flag )
{
if( d1 > d2 ) /* make d1 <= d2 */
{
d1 ^= d2;
d2 ^= d1;
d1 ^= d2;
}
for( ; d1 <= d2; d1++ )
hist_row[d1]++;
}
else
{
for( ; d1 >= 0; d1-- )
hist_row[d1]++;
for( ; d2 >= 0; d2-- )
hist_row[d2]++;
}
}
else /* 1st pass */
{
d1 = CV_IMAX( d1, d2 );
dist = CV_IMAX( dist, d1 );
}
} /* end of processing of edge pair */
} /* end of internal loop */
if( pass == 1 )
{
double scale = dist * buffer[i];
dist_scale = MAX( dist_scale, scale );
}
}
} /* end of external loop */
if( pass == 1 )
{
dist_scale = (dist_dim - 0.51) / dist_scale;
}
} /* end of pass on loops */
/* convert hist to floats */
for( i = 0; i < hist_size; i++ )
{
((float *) pghi)[i] = (float) pghi[i];
}
if( buffer != local_buffer_ptr )
cvFree( &buffer );
return CV_OK;
}
CV_IMPL void
cvCalcPGH( const CvSeq * contour, CvHistogram * hist )
{
int size[CV_MAX_DIM];
int dims;
if( !CV_IS_HIST(hist))
CV_Error( CV_StsBadArg, "The histogram header is invalid " );
if( CV_IS_SPARSE_HIST( hist ))
CV_Error( CV_StsUnsupportedFormat, "Sparse histogram are not supported" );
dims = cvGetDims( hist->bins, size );
if( dims != 2 )
CV_Error( CV_StsBadSize, "The histogram must be two-dimensional" );
if( !CV_IS_SEQ_POINT_SET( contour ) || CV_SEQ_ELTYPE( contour ) != CV_32SC2 )
CV_Error( CV_StsUnsupportedFormat, "The contour is not valid or the point type is not supported" );
IPPI_CALL( icvCalcPGH( contour, ((CvMatND*)(hist->bins))->data.fl, size[0], size[1] ));
}
/* End of file. */

View File

@@ -0,0 +1,42 @@
/*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"

View File

@@ -0,0 +1,67 @@
/*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*/
#ifndef __OPENCV_LEGACY_PRECOMP_H__
#define __OPENCV_LEGACY_PRECOMP_H__
#if _MSC_VER >= 1200
#pragma warning( disable: 4251 4710 4711 4514 4996 ) /* function AAA selected for automatic inline expansion */
#endif
#include "opencv2/legacy/legacy.hpp"
#include "opencv2/video/tracking.hpp"
#include "opencv2/core/internal.hpp"
#include "_matrix.h"
typedef unsigned short ushort;
CV_INLINE bool operator == (CvSize size1, CvSize size2 );
CV_INLINE bool operator == (CvSize size1, CvSize size2 )
{
return size1.width == size2.width && size1.height == size2.height;
}
CV_INLINE bool operator != (CvSize size1, CvSize size2 );
CV_INLINE bool operator != (CvSize size1, CvSize size2 )
{
return size1.width != size2.width || size1.height != size2.height;
}
#endif /* __CVAUX_H__ */

View File

@@ -0,0 +1,163 @@
/*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 "_vm.h"
/* Valery Mosyagin */
static CvStatus
icvFindRuns( int numLines, /* number of scanlines */
uchar * prewarp_1, /* prewarp image 1 */
uchar * prewarp_2, /* prewarp image 2 */
int *line_lens_1, /* line lengths 1 */
int *line_lens_2, /* line lengths 2 */
int *runs_1, /* result runs 1 */
int *runs_2, /* result runs 2 */
int *num_runs_1, /* numbers of first runs */
int *num_runs_2 )
{
CvStatus err;
err = icvFindRunsInOneImage( numLines, prewarp_1, line_lens_1, runs_1, num_runs_1 );
if( err != CV_NO_ERR )
return err;
err = icvFindRunsInOneImage( numLines, prewarp_2, line_lens_2, runs_2, num_runs_2 );
return err;
}
/*======================================================================================*/
CV_INLINE int
icvGetColor( uchar * valueRGB )
{
int R = *valueRGB;
int G = *(valueRGB + 1);
int B = *(valueRGB + 2);
return ( ((R + G + B) >> 3) & 0xFFFC );
} /* vm_GetColor */
/*======================================================================================*/
CvStatus
icvFindRunsInOneImage( int numLines, /* number of scanlines */
uchar * prewarp, /* prewarp image */
int *line_lens, /* line lengths in pixels */
int *runs, /* result runs */
int *num_runs )
{
int epiLine;
int run_index;
int curr_color;
int index;
int color;
uchar *curr_point;
int num;
run_index = 0;
curr_point = prewarp;
for( epiLine = 0; epiLine < numLines; epiLine++ )
{
curr_color = icvGetColor( curr_point );
runs[run_index++] = 0;
runs[run_index++] = curr_color;
curr_point += 3;
num = 1;
for( index = 1; index < line_lens[epiLine]; index++ )
{
color = icvGetColor( curr_point );
if( color != curr_color )
{
runs[run_index++] = index;
runs[run_index++] = color;
curr_color = color;
num++;
}
curr_point += 3;
}
runs[run_index++] = index;
num_runs[epiLine] = num;
}
return CV_NO_ERR;
}
/*======================================================================================*/
CV_IMPL void
cvFindRuns( int numLines, /* number of scanlines */
uchar * prewarp_1, /* prewarp image 1 */
uchar * prewarp_2, /* prewarp image 2 */
int *line_lens_1, /* line lengths 1 */
int *line_lens_2, /* line lengths 2 */
int *runs_1, /* result runs 1 */
int *runs_2, /* result runs 2 */
int *num_runs_1, /* numbers of first runs */
int *num_runs_2 )
{
IPPI_CALL( icvFindRuns( numLines, /* number of scanlines */
prewarp_1, /* prewarp image 1 */
prewarp_2, /* prewarp image 2 */
line_lens_1, /* line lengths 1 */
line_lens_2, /* line lengths 2 */
runs_1, /* result runs 1 */
runs_2, /* result runs 2 */
num_runs_1, /* numbers of first runs */
num_runs_2 ));
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,585 @@
/*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"
typedef struct Seg
{
ushort y;
ushort l;
ushort r;
ushort Prevl;
ushort Prevr;
short fl;
}
Seg;
#define UP 1
#define DOWN -1
#define PUSH(Y,IL,IR,IPL,IPR,FL) { stack[StIn].y=(ushort)(Y); \
stack[StIn].l=(ushort)(IL); \
stack[StIn].r=(ushort)(IR); \
stack[StIn].Prevl=(ushort)(IPL); \
stack[StIn].Prevr=(ushort)(IPR); \
stack[StIn].fl=(short)(FL); \
StIn++; }
#define POP(Y,IL,IR,IPL,IPR,FL) { StIn--; \
Y=stack[StIn].y; \
IL=stack[StIn].l; \
IR=stack[StIn].r;\
IPL=stack[StIn].Prevl; \
IPR=stack[StIn].Prevr; \
FL=stack[StIn].fl; }
#define DIFF(p1,p2) ((unsigned)((p1)[0] - (p2)[0] + d_lw)<=Interval && \
(unsigned)((p1)[1] - (p2)[1] + d_lw)<=Interval && \
(unsigned)((p1)[2] - (p2)[2] + d_lw)<=Interval)
/*#define DIFF(p1,p2) (CV_IABS((p1)[0] - (p2)[0]) + \
CV_IABS((p1)[1] - (p2)[1]) + \
CV_IABS((p1)[2] - (p2)[2]) <=Interval )*/
static CvStatus
icvSegmFloodFill_Stage1( uchar* pImage, int step,
uchar* pMask, int maskStep,
CvSize /*roi*/, CvPoint seed,
int* newVal, int d_lw, int d_up,
CvConnectedComp * region,
void *pStack )
{
uchar* img = pImage + step * seed.y;
uchar* mask = pMask + maskStep * (seed.y + 1);
unsigned Interval = (unsigned) (d_up + d_lw);
Seg *stack = (Seg*)pStack;
int StIn = 0;
int i, L, R;
int area = 0;
int sum[] = { 0, 0, 0 };
int XMin, XMax, YMin = seed.y, YMax = seed.y;
int val0[3];
L = R = seed.x;
img = pImage + seed.y*step;
mask = pMask + seed.y*maskStep;
mask[L] = 1;
val0[0] = img[seed.x*3];
val0[1] = img[seed.x*3 + 1];
val0[2] = img[seed.x*3 + 2];
while( DIFF( img + (R+1)*3, /*img + R*3*/val0 ) && !mask[R + 1] )
mask[++R] = 2;
while( DIFF( img + (L-1)*3, /*img + L*3*/val0 ) && !mask[L - 1] )
mask[--L] = 2;
XMax = R;
XMin = L;
PUSH( seed.y, L, R, R + 1, R, UP );
while( StIn )
{
int k, YC, PL, PR, flag/*, curstep*/;
POP( YC, L, R, PL, PR, flag );
int data[][3] = { {-flag, L, R}, {flag, L, PL-1}, {flag,PR+1,R}};
if( XMax < R )
XMax = R;
if( XMin > L )
XMin = L;
if( YMax < YC )
YMax = YC;
if( YMin > YC )
YMin = YC;
for( k = 0; k < 3; k++ )
{
flag = data[k][0];
/*curstep = flag * step;*/
img = pImage + (YC + flag) * step;
mask = pMask + (YC + flag) * maskStep;
int left = data[k][1];
int right = data[k][2];
for( i = left; i <= right; i++ )
{
if( !mask[i] && DIFF( img + i*3, /*img - curstep + i*3*/val0 ))
{
int j = i;
mask[i] = 2;
while( !mask[j - 1] && DIFF( img + (j - 1)*3, /*img + j*3*/val0 ))
mask[--j] = 2;
while( !mask[i + 1] &&
(DIFF( img + (i+1)*3, /*img + i*3*/val0 ) ||
(DIFF( img + (i+1)*3, /*img + (i+1)*3 - curstep*/val0) && i < R)))
mask[++i] = 2;
PUSH( YC + flag, j, i, L, R, -flag );
i++;
}
}
}
img = pImage + YC * step;
for( i = L; i <= R; i++ )
{
sum[0] += img[i*3];
sum[1] += img[i*3 + 1];
sum[2] += img[i*3 + 2];
}
area += R - L + 1;
}
region->area = area;
region->rect.x = XMin;
region->rect.y = YMin;
region->rect.width = XMax - XMin + 1;
region->rect.height = YMax - YMin + 1;
region->value = cvScalarAll(0);
{
double inv_area = area ? 1./area : 0;
newVal[0] = cvRound( sum[0] * inv_area );
newVal[1] = cvRound( sum[1] * inv_area );
newVal[2] = cvRound( sum[2] * inv_area );
}
return CV_NO_ERR;
}
#undef PUSH
#undef POP
#undef DIFF
static CvStatus
icvSegmFloodFill_Stage2( uchar* pImage, int step,
uchar* pMask, int maskStep,
CvSize /*roi*/, int* newVal,
CvRect rect )
{
uchar* img = pImage + step * rect.y + rect.x * 3;
uchar* mask = pMask + maskStep * rect.y + rect.x;
uchar uv[] = { (uchar)newVal[0], (uchar)newVal[1], (uchar)newVal[2] };
int x, y;
for( y = 0; y < rect.height; y++, img += step, mask += maskStep )
for( x = 0; x < rect.width; x++ )
if( mask[x] == 2 )
{
mask[x] = 1;
img[x*3] = uv[0];
img[x*3+1] = uv[1];
img[x*3+2] = uv[2];
}
return CV_OK;
}
#if 0
static void color_derv( const CvArr* srcArr, CvArr* dstArr, int thresh )
{
static int tab[] = { 0, 2, 2, 1 };
uchar *src = 0, *dst = 0;
int dst_step, src_step;
int x, y;
CvSize size;
cvGetRawData( srcArr, (uchar**)&src, &src_step, &size );
cvGetRawData( dstArr, (uchar**)&dst, &dst_step, 0 );
memset( dst, 0, size.width*sizeof(dst[0]));
memset( (uchar*)dst + dst_step*(size.height-1), 0, size.width*sizeof(dst[0]));
src += 3;
#define CV_IABS(a) (((a) ^ ((a) < 0 ? -1 : 0)) - ((a) < 0 ? -1 : 0))
for( y = 1; y < size.height - 1; y++ )
{
src += src_step;
dst += dst_step;
uchar* src0 = src;
dst[0] = dst[size.width - 1] = 0;
for( x = 1; x < size.width - 1; x++, src += 3 )
{
/*int d[3];
int ad[3];
int f0, f1;
int val;*/
int m[3];
double val;
//double xx, yy;
int dh[3];
int dv[3];
dh[0] = src[0] - src[-3];
dv[0] = src[0] - src[-src_step];
dh[1] = src[1] - src[-2];
dv[1] = src[1] - src[1-src_step];
dh[2] = src[2] - src[-1];
dv[2] = src[2] - src[2-src_step];
m[0] = dh[0]*dh[0] + dh[1]*dh[1] + dh[2]*dh[2];
m[2] = dh[0]*dv[0] + dh[1]*dv[1] + dh[2]*dv[2];
m[1] = dv[0]*dv[0] + dv[1]*dv[1] + dh[2]*dh[2];
val = (m[0] + m[2]) +
sqrt(((double)((double)m[0] - m[2]))*(m[0] - m[2]) + (4.*m[1])*m[1]);
/*
xx = m[1];
yy = v - m[0];
v /= sqrt(xx*xx + yy*yy) + 1e-7;
xx *= v;
yy *= v;
dx[x] = (short)cvRound(xx);
dy[x] = (short)cvRound(yy);
//dx[x] = (short)cvRound(v);
//dx[x] = dy[x] = (short)v;
d[0] = src[0] - src[-3];
ad[0] = CV_IABS(d[0]);
d[1] = src[1] - src[-2];
ad[1] = CV_IABS(d[1]);
d[2] = src[2] - src[-1];
ad[2] = CV_IABS(d[2]);
f0 = ad[1] > ad[0];
f1 = ad[2] > ad[f0];
val = d[tab[f0*2 + f1]];
d[0] = src[0] - src[-src_step];
ad[0] = CV_IABS(d[0]);
d[1] = src[1] - src[1-src_step];
ad[1] = CV_IABS(d[1]);
d[2] = src[2] - src[2-src_step];
ad[2] = CV_IABS(d[2]);
f0 = ad[1] > ad[0];
f1 = ad[2] > ad[f0];
dst[x] = (uchar)(val + d[tab[f0*2 + f1]] > thresh ? 255 : 0);*/
dst[x] = (uchar)(val > thresh);
}
src = src0;
}
}
#endif
const CvPoint icvCodeDeltas[8] =
{ {1, 0}, {1, -1}, {0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1} };
static CvSeq*
icvGetComponent( uchar* img, int step, CvRect rect,
CvMemStorage* storage )
{
const char nbd = 4;
int deltas[16];
int x, y;
CvSeq* exterior = 0;
char* ptr;
/* initialize local state */
CV_INIT_3X3_DELTAS( deltas, step, 1 );
memcpy( deltas + 8, deltas, 8 * sizeof( deltas[0] ));
ptr = (char*)(img + step*rect.y);
rect.width += rect.x;
rect.height += rect.y;
for( y = rect.y; y < rect.height; y++, ptr += step )
{
int prev = ptr[rect.x - 1] & -2;
for( x = rect.x; x < rect.width; x++ )
{
int p = ptr[x] & -2;
//assert( exterior || ((p | prev) & -4) == 0 );
if( p != prev )
{
CvSeq *seq = 0;
int is_hole = 0;
CvSeqWriter writer;
char *i0, *i1, *i3, *i4 = 0;
int prev_s = -1, s, s_end;
CvPoint pt = { x, y };
if( !(prev == 0 && p == 2) ) /* if not external contour */
{
/* check hole */
if( p != 0 || prev < 1 )
{
prev = p;
continue;
}
is_hole = 1;
if( !exterior )
{
assert(0);
return 0;
}
}
cvStartWriteSeq( CV_SEQ_CONTOUR | (is_hole ? CV_SEQ_FLAG_HOLE : 0),
sizeof(CvContour), sizeof(CvPoint), storage, &writer );
s_end = s = is_hole ? 0 : 4;
i0 = ptr + x - is_hole;
do
{
s = (s - 1) & 7;
i1 = i0 + deltas[s];
if( (*i1 & -2) != 0 )
break;
}
while( s != s_end );
if( s == s_end ) /* single pixel domain */
{
*i0 = (char) (nbd | -128);
CV_WRITE_SEQ_ELEM( pt, writer );
}
else
{
i3 = i0;
prev_s = s ^ 4;
/* follow border */
for( ;; )
{
s_end = s;
for( ;; )
{
i4 = i3 + deltas[++s];
if( (*i4 & -2) != 0 )
break;
}
s &= 7;
/* check "right" bound */
if( (unsigned) (s - 1) < (unsigned) s_end )
{
*i3 = (char) (nbd | -128);
}
else if( *i3 > 0 )
{
*i3 = nbd;
}
if( s != prev_s )
{
CV_WRITE_SEQ_ELEM( pt, writer );
prev_s = s;
}
pt.x += icvCodeDeltas[s].x;
pt.y += icvCodeDeltas[s].y;
if( i4 == i0 && i3 == i1 )
break;
i3 = i4;
s = (s + 4) & 7;
} /* end of border following loop */
}
seq = cvEndWriteSeq( &writer );
cvContourBoundingRect( seq, 1 );
if( !is_hole )
exterior = seq;
else
{
seq->v_prev = exterior;
seq->h_next = exterior->v_next;
if( seq->h_next )
seq->h_next->h_prev = seq;
exterior->v_next = seq;
}
prev = ptr[x] & -2;
}
}
}
return exterior;
}
CV_IMPL CvSeq*
cvSegmentImage( const CvArr* srcarr, CvArr* dstarr,
double canny_threshold,
double ffill_threshold,
CvMemStorage* storage )
{
CvSeq* root = 0;
CvMat* gray = 0;
CvMat* canny = 0;
//CvMat* temp = 0;
void* stack = 0;
CV_FUNCNAME( "cvSegmentImage" );
__BEGIN__;
CvMat srcstub, *src;
CvMat dststub, *dst;
CvMat* mask;
CvSize size;
CvPoint pt;
int ffill_lw_up = cvRound( fabs(ffill_threshold) );
CvSeq* prev_seq = 0;
CV_CALL( src = cvGetMat( srcarr, &srcstub ));
CV_CALL( dst = cvGetMat( dstarr, &dststub ));
size = cvGetSize( src );
CV_CALL( gray = cvCreateMat( size.height, size.width, CV_8UC1 ));
CV_CALL( canny = cvCreateMat( size.height, size.width, CV_8UC1 ));
//CV_CALL( temp = cvCreateMat( size.height/2, size.width/2, CV_8UC3 ));
CV_CALL( stack = cvAlloc( size.width * size.height * sizeof(Seg)));
cvCvtColor( src, gray, CV_BGR2GRAY );
cvCanny( gray, canny, 0/*canny_threshold*0.4*/, canny_threshold, 3 );
cvThreshold( canny, canny, 1, 1, CV_THRESH_BINARY );
//cvZero( canny );
//color_derv( src, canny, canny_threshold );
//cvPyrDown( src, temp );
//cvPyrUp( temp, dst );
//src = dst;
mask = canny; // a new name for new role
// make a non-zero border.
cvRectangle( mask, cvPoint(0,0), cvPoint(size.width-1,size.height-1), cvScalarAll(1), 1 );
for( pt.y = 0; pt.y < size.height; pt.y++ )
{
for( pt.x = 0; pt.x < size.width; pt.x++ )
{
if( mask->data.ptr[mask->step*pt.y + pt.x] == 0 )
{
CvConnectedComp region;
int avgVal[3] = { 0, 0, 0 };
icvSegmFloodFill_Stage1( src->data.ptr, src->step,
mask->data.ptr, mask->step,
size, pt, avgVal,
ffill_lw_up, ffill_lw_up,
&region, stack );
/*avgVal[0] = (avgVal[0] + 15) & -32;
if( avgVal[0] > 255 )
avgVal[0] = 255;
avgVal[1] = (avgVal[1] + 15) & -32;
if( avgVal[1] > 255 )
avgVal[1] = 255;
avgVal[2] = (avgVal[2] + 15) & -32;
if( avgVal[2] > 255 )
avgVal[2] = 255;*/
if( storage )
{
CvSeq* tmpseq = icvGetComponent( mask->data.ptr, mask->step,
region.rect, storage );
if( tmpseq != 0 )
{
((CvContour*)tmpseq)->color = avgVal[0] + (avgVal[1] << 8) + (avgVal[2] << 16);
tmpseq->h_prev = prev_seq;
if( prev_seq )
prev_seq->h_next = tmpseq;
else
root = tmpseq;
prev_seq = tmpseq;
}
}
icvSegmFloodFill_Stage2( dst->data.ptr, dst->step,
mask->data.ptr, mask->step,
size, avgVal,
region.rect );
}
}
}
__END__;
//cvReleaseMat( &temp );
cvReleaseMat( &gray );
cvReleaseMat( &canny );
cvFree( &stack );
return root;
}
/* End of file. */

View File

@@ -0,0 +1,428 @@
/*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"
#define _CV_SNAKE_BIG 2.e+38f
#define _CV_SNAKE_IMAGE 1
#define _CV_SNAKE_GRAD 2
/*F///////////////////////////////////////////////////////////////////////////////////////
// Name: icvSnake8uC1R
// Purpose:
// Context:
// Parameters:
// src - source image,
// srcStep - its step in bytes,
// roi - size of ROI,
// pt - pointer to snake points array
// n - size of points array,
// alpha - pointer to coefficient of continuity energy,
// beta - pointer to coefficient of curvature energy,
// gamma - pointer to coefficient of image energy,
// coeffUsage - if CV_VALUE - alpha, beta, gamma point to single value
// if CV_MATAY - point to arrays
// criteria - termination criteria.
// scheme - image energy scheme
// if _CV_SNAKE_IMAGE - image intensity is energy
// if _CV_SNAKE_GRAD - magnitude of gradient is energy
// Returns:
//F*/
static CvStatus
icvSnake8uC1R( unsigned char *src,
int srcStep,
CvSize roi,
CvPoint * pt,
int n,
float *alpha,
float *beta,
float *gamma,
int coeffUsage, CvSize win, CvTermCriteria criteria, int scheme )
{
int i, j, k;
int neighbors = win.height * win.width;
int centerx = win.width >> 1;
int centery = win.height >> 1;
float invn;
int iteration = 0;
int converged = 0;
float *Econt;
float *Ecurv;
float *Eimg;
float *E;
float _alpha, _beta, _gamma;
/*#ifdef GRAD_SNAKE */
float *gradient = NULL;
uchar *map = NULL;
int map_width = ((roi.width - 1) >> 3) + 1;
int map_height = ((roi.height - 1) >> 3) + 1;
#define WTILE_SIZE 8
#define TILE_SIZE (WTILE_SIZE + 2)
short dx[TILE_SIZE*TILE_SIZE], dy[TILE_SIZE*TILE_SIZE];
CvMat _dx = cvMat( TILE_SIZE, TILE_SIZE, CV_16SC1, dx );
CvMat _dy = cvMat( TILE_SIZE, TILE_SIZE, CV_16SC1, dy );
CvMat _src = cvMat( roi.height, roi.width, CV_8UC1, src );
cv::Ptr<cv::FilterEngine> pX, pY;
/* inner buffer of convolution process */
//char ConvBuffer[400];
/*#endif */
/* check bad arguments */
if( src == NULL )
return CV_NULLPTR_ERR;
if( (roi.height <= 0) || (roi.width <= 0) )
return CV_BADSIZE_ERR;
if( srcStep < roi.width )
return CV_BADSIZE_ERR;
if( pt == NULL )
return CV_NULLPTR_ERR;
if( n < 3 )
return CV_BADSIZE_ERR;
if( alpha == NULL )
return CV_NULLPTR_ERR;
if( beta == NULL )
return CV_NULLPTR_ERR;
if( gamma == NULL )
return CV_NULLPTR_ERR;
if( coeffUsage != CV_VALUE && coeffUsage != CV_ARRAY )
return CV_BADFLAG_ERR;
if( (win.height <= 0) || (!(win.height & 1)))
return CV_BADSIZE_ERR;
if( (win.width <= 0) || (!(win.width & 1)))
return CV_BADSIZE_ERR;
invn = 1 / ((float) n);
if( scheme == _CV_SNAKE_GRAD )
{
pX = cv::createDerivFilter( CV_8U, CV_16S, 1, 0, 3, cv::BORDER_REPLICATE );
pY = cv::createDerivFilter( CV_8U, CV_16S, 0, 1, 3, cv::BORDER_REPLICATE );
gradient = (float *) cvAlloc( roi.height * roi.width * sizeof( float ));
map = (uchar *) cvAlloc( map_width * map_height );
/* clear map - no gradient computed */
memset( (void *) map, 0, map_width * map_height );
}
Econt = (float *) cvAlloc( neighbors * sizeof( float ));
Ecurv = (float *) cvAlloc( neighbors * sizeof( float ));
Eimg = (float *) cvAlloc( neighbors * sizeof( float ));
E = (float *) cvAlloc( neighbors * sizeof( float ));
while( !converged )
{
float ave_d = 0;
int moved = 0;
converged = 0;
iteration++;
/* compute average distance */
for( i = 1; i < n; i++ )
{
int diffx = pt[i - 1].x - pt[i].x;
int diffy = pt[i - 1].y - pt[i].y;
ave_d += cvSqrt( (float) (diffx * diffx + diffy * diffy) );
}
ave_d += cvSqrt( (float) ((pt[0].x - pt[n - 1].x) *
(pt[0].x - pt[n - 1].x) +
(pt[0].y - pt[n - 1].y) * (pt[0].y - pt[n - 1].y)));
ave_d *= invn;
/* average distance computed */
for( i = 0; i < n; i++ )
{
/* Calculate Econt */
float maxEcont = 0;
float maxEcurv = 0;
float maxEimg = 0;
float minEcont = _CV_SNAKE_BIG;
float minEcurv = _CV_SNAKE_BIG;
float minEimg = _CV_SNAKE_BIG;
float Emin = _CV_SNAKE_BIG;
int offsetx = 0;
int offsety = 0;
float tmp;
/* compute bounds */
int left = MIN( pt[i].x, win.width >> 1 );
int right = MIN( roi.width - 1 - pt[i].x, win.width >> 1 );
int upper = MIN( pt[i].y, win.height >> 1 );
int bottom = MIN( roi.height - 1 - pt[i].y, win.height >> 1 );
maxEcont = 0;
minEcont = _CV_SNAKE_BIG;
for( j = -upper; j <= bottom; j++ )
{
for( k = -left; k <= right; k++ )
{
int diffx, diffy;
float energy;
if( i == 0 )
{
diffx = pt[n - 1].x - (pt[i].x + k);
diffy = pt[n - 1].y - (pt[i].y + j);
}
else
{
diffx = pt[i - 1].x - (pt[i].x + k);
diffy = pt[i - 1].y - (pt[i].y + j);
}
Econt[(j + centery) * win.width + k + centerx] = energy =
(float) fabs( ave_d -
cvSqrt( (float) (diffx * diffx + diffy * diffy) ));
maxEcont = MAX( maxEcont, energy );
minEcont = MIN( minEcont, energy );
}
}
tmp = maxEcont - minEcont;
tmp = (tmp == 0) ? 0 : (1 / tmp);
for( k = 0; k < neighbors; k++ )
{
Econt[k] = (Econt[k] - minEcont) * tmp;
}
/* Calculate Ecurv */
maxEcurv = 0;
minEcurv = _CV_SNAKE_BIG;
for( j = -upper; j <= bottom; j++ )
{
for( k = -left; k <= right; k++ )
{
int tx, ty;
float energy;
if( i == 0 )
{
tx = pt[n - 1].x - 2 * (pt[i].x + k) + pt[i + 1].x;
ty = pt[n - 1].y - 2 * (pt[i].y + j) + pt[i + 1].y;
}
else if( i == n - 1 )
{
tx = pt[i - 1].x - 2 * (pt[i].x + k) + pt[0].x;
ty = pt[i - 1].y - 2 * (pt[i].y + j) + pt[0].y;
}
else
{
tx = pt[i - 1].x - 2 * (pt[i].x + k) + pt[i + 1].x;
ty = pt[i - 1].y - 2 * (pt[i].y + j) + pt[i + 1].y;
}
Ecurv[(j + centery) * win.width + k + centerx] = energy =
(float) (tx * tx + ty * ty);
maxEcurv = MAX( maxEcurv, energy );
minEcurv = MIN( minEcurv, energy );
}
}
tmp = maxEcurv - minEcurv;
tmp = (tmp == 0) ? 0 : (1 / tmp);
for( k = 0; k < neighbors; k++ )
{
Ecurv[k] = (Ecurv[k] - minEcurv) * tmp;
}
/* Calculate Eimg */
for( j = -upper; j <= bottom; j++ )
{
for( k = -left; k <= right; k++ )
{
float energy;
if( scheme == _CV_SNAKE_GRAD )
{
/* look at map and check status */
int x = (pt[i].x + k)/WTILE_SIZE;
int y = (pt[i].y + j)/WTILE_SIZE;
if( map[y * map_width + x] == 0 )
{
int l, m;
/* evaluate block location */
int upshift = y ? 1 : 0;
int leftshift = x ? 1 : 0;
int bottomshift = MIN( 1, roi.height - (y + 1)*WTILE_SIZE );
int rightshift = MIN( 1, roi.width - (x + 1)*WTILE_SIZE );
CvRect g_roi = { x*WTILE_SIZE - leftshift, y*WTILE_SIZE - upshift,
leftshift + WTILE_SIZE + rightshift, upshift + WTILE_SIZE + bottomshift };
CvMat _src1;
cvGetSubArr( &_src, &_src1, g_roi );
cv::Mat _src_ = cv::cvarrToMat(&_src1);
cv::Mat _dx_ = cv::cvarrToMat(&_dx);
cv::Mat _dy_ = cv::cvarrToMat(&_dy);
pX->apply( _src_, _dx_, cv::Rect(0,0,-1,-1), cv::Point(), true );
pY->apply( _src_, _dy_, cv::Rect(0,0,-1,-1), cv::Point(), true );
for( l = 0; l < WTILE_SIZE + bottomshift; l++ )
{
for( m = 0; m < WTILE_SIZE + rightshift; m++ )
{
gradient[(y*WTILE_SIZE + l) * roi.width + x*WTILE_SIZE + m] =
(float) (dx[(l + upshift) * TILE_SIZE + m + leftshift] *
dx[(l + upshift) * TILE_SIZE + m + leftshift] +
dy[(l + upshift) * TILE_SIZE + m + leftshift] *
dy[(l + upshift) * TILE_SIZE + m + leftshift]);
}
}
map[y * map_width + x] = 1;
}
Eimg[(j + centery) * win.width + k + centerx] = energy =
gradient[(pt[i].y + j) * roi.width + pt[i].x + k];
}
else
{
Eimg[(j + centery) * win.width + k + centerx] = energy =
src[(pt[i].y + j) * srcStep + pt[i].x + k];
}
maxEimg = MAX( maxEimg, energy );
minEimg = MIN( minEimg, energy );
}
}
tmp = (maxEimg - minEimg);
tmp = (tmp == 0) ? 0 : (1 / tmp);
for( k = 0; k < neighbors; k++ )
{
Eimg[k] = (minEimg - Eimg[k]) * tmp;
}
/* locate coefficients */
if( coeffUsage == CV_VALUE)
{
_alpha = *alpha;
_beta = *beta;
_gamma = *gamma;
}
else
{
_alpha = alpha[i];
_beta = beta[i];
_gamma = gamma[i];
}
/* Find Minimize point in the neighbors */
for( k = 0; k < neighbors; k++ )
{
E[k] = _alpha * Econt[k] + _beta * Ecurv[k] + _gamma * Eimg[k];
}
Emin = _CV_SNAKE_BIG;
for( j = -upper; j <= bottom; j++ )
{
for( k = -left; k <= right; k++ )
{
if( E[(j + centery) * win.width + k + centerx] < Emin )
{
Emin = E[(j + centery) * win.width + k + centerx];
offsetx = k;
offsety = j;
}
}
}
if( offsetx || offsety )
{
pt[i].x += offsetx;
pt[i].y += offsety;
moved++;
}
}
converged = (moved == 0);
if( (criteria.type & CV_TERMCRIT_ITER) && (iteration >= criteria.max_iter) )
converged = 1;
if( (criteria.type & CV_TERMCRIT_EPS) && (moved <= criteria.epsilon) )
converged = 1;
}
cvFree( &Econt );
cvFree( &Ecurv );
cvFree( &Eimg );
cvFree( &E );
if( scheme == _CV_SNAKE_GRAD )
{
cvFree( &gradient );
cvFree( &map );
}
return CV_OK;
}
CV_IMPL void
cvSnakeImage( const IplImage* src, CvPoint* points,
int length, float *alpha,
float *beta, float *gamma,
int coeffUsage, CvSize win,
CvTermCriteria criteria, int calcGradient )
{
uchar *data;
CvSize size;
int step;
if( src->nChannels != 1 )
CV_Error( CV_BadNumChannels, "input image has more than one channel" );
if( src->depth != IPL_DEPTH_8U )
CV_Error( CV_BadDepth, cvUnsupportedFormat );
cvGetRawData( src, &data, &step, &size );
IPPI_CALL( icvSnake8uC1R( data, step, size, points, length,
alpha, beta, gamma, coeffUsage, win, criteria,
calcGradient ? _CV_SNAKE_GRAD : _CV_SNAKE_IMAGE ));
}
/* end of file */

View File

@@ -0,0 +1,176 @@
/*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"
CV_IMPL int
icvSubdiv2DCheck( CvSubdiv2D* subdiv )
{
int i, j, total = subdiv->edges->total;
CV_Assert( subdiv != 0 );
for( i = 0; i < total; i++ )
{
CvQuadEdge2D* edge = (CvQuadEdge2D*)cvGetSetElem(subdiv->edges,i);
if( edge && CV_IS_SET_ELEM( edge ))
{
for( j = 0; j < 4; j++ )
{
CvSubdiv2DEdge e = (CvSubdiv2DEdge)edge + j;
CvSubdiv2DEdge o_next = cvSubdiv2DNextEdge(e);
CvSubdiv2DEdge o_prev = cvSubdiv2DGetEdge(e, CV_PREV_AROUND_ORG );
CvSubdiv2DEdge d_prev = cvSubdiv2DGetEdge(e, CV_PREV_AROUND_DST );
CvSubdiv2DEdge d_next = cvSubdiv2DGetEdge(e, CV_NEXT_AROUND_DST );
// check points
if( cvSubdiv2DEdgeOrg(e) != cvSubdiv2DEdgeOrg(o_next))
return 0;
if( cvSubdiv2DEdgeOrg(e) != cvSubdiv2DEdgeOrg(o_prev))
return 0;
if( cvSubdiv2DEdgeDst(e) != cvSubdiv2DEdgeDst(d_next))
return 0;
if( cvSubdiv2DEdgeDst(e) != cvSubdiv2DEdgeDst(d_prev))
return 0;
if( j % 2 == 0 )
{
if( cvSubdiv2DEdgeDst(o_next) != cvSubdiv2DEdgeOrg(d_prev))
return 0;
if( cvSubdiv2DEdgeDst(o_prev) != cvSubdiv2DEdgeOrg(d_next))
return 0;
if( cvSubdiv2DGetEdge(cvSubdiv2DGetEdge(cvSubdiv2DGetEdge(
e,CV_NEXT_AROUND_LEFT),CV_NEXT_AROUND_LEFT),CV_NEXT_AROUND_LEFT) != e )
return 0;
if( cvSubdiv2DGetEdge(cvSubdiv2DGetEdge(cvSubdiv2DGetEdge(
e,CV_NEXT_AROUND_RIGHT),CV_NEXT_AROUND_RIGHT),CV_NEXT_AROUND_RIGHT) != e)
return 0;
}
}
}
}
return 1;
}
static void
draw_subdiv_facet( CvSubdiv2D * subdiv, IplImage * dst, IplImage * src, CvSubdiv2DEdge edge )
{
CvSubdiv2DEdge t = edge;
int i, count = 0;
CvPoint local_buf[100];
CvPoint *buf = local_buf;
// count number of edges in facet
do
{
count++;
t = cvSubdiv2DGetEdge( t, CV_NEXT_AROUND_LEFT );
}
while( t != edge && count < subdiv->quad_edges * 4 );
if( count * sizeof( buf[0] ) > sizeof( local_buf ))
{
buf = (CvPoint *) malloc( count * sizeof( buf[0] ));
}
// gather points
t = edge;
for( i = 0; i < count; i++ )
{
CvSubdiv2DPoint *pt = cvSubdiv2DEdgeOrg( t );
if( !pt )
break;
assert( fabs( pt->pt.x ) < 10000 && fabs( pt->pt.y ) < 10000 );
buf[i] = cvPoint( cvRound( pt->pt.x ), cvRound( pt->pt.y ));
t = cvSubdiv2DGetEdge( t, CV_NEXT_AROUND_LEFT );
}
if( i == count )
{
CvSubdiv2DPoint *pt = cvSubdiv2DEdgeDst( cvSubdiv2DRotateEdge( edge, 1 ));
CvPoint ip = cvPoint( cvRound( pt->pt.x ), cvRound( pt->pt.y ));
CvScalar color = {{0,0,0,0}};
//printf("count = %d, (%d,%d)\n", ip.x, ip.y );
if( 0 <= ip.x && ip.x < src->width && 0 <= ip.y && ip.y < src->height )
{
uchar *ptr = (uchar*)(src->imageData + ip.y * src->widthStep + ip.x * 3);
color = CV_RGB( ptr[2], ptr[1], ptr[0] );
}
cvFillConvexPoly( dst, buf, count, color );
//draw_subdiv_point( dst, pt->pt, CV_RGB(0,0,0));
}
if( buf != local_buf )
free( buf );
}
CV_IMPL void
icvDrawMosaic( CvSubdiv2D * subdiv, IplImage * src, IplImage * dst )
{
int i, total = subdiv->edges->total;
cvCalcSubdivVoronoi2D( subdiv );
//icvSet( dst, 255 );
for( i = 0; i < total; i++ )
{
CvQuadEdge2D *edge = (CvQuadEdge2D *) cvGetSetElem( subdiv->edges, i );
if( edge && CV_IS_SET_ELEM( edge ))
{
CvSubdiv2DEdge e = (CvSubdiv2DEdge) edge;
// left
draw_subdiv_facet( subdiv, dst, src, cvSubdiv2DRotateEdge( e, 1 ));
// right
draw_subdiv_facet( subdiv, dst, src, cvSubdiv2DRotateEdge( e, 3 ));
}
}
}
/* End of file. */

View File

@@ -0,0 +1,648 @@
/*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*/
/****************************************************************************************\
Calculation of a texture descriptors from GLCM (Grey Level Co-occurrence Matrix'es)
The code was submitted by Daniel Eaton [danieljameseaton@yahoo.com]
\****************************************************************************************/
#include "precomp.hpp"
#include <math.h>
#include <assert.h>
#define CV_MAX_NUM_GREY_LEVELS_8U 256
struct CvGLCM
{
int matrixSideLength;
int numMatrices;
double*** matrices;
int numLookupTableElements;
int forwardLookupTable[CV_MAX_NUM_GREY_LEVELS_8U];
int reverseLookupTable[CV_MAX_NUM_GREY_LEVELS_8U];
double** descriptors;
int numDescriptors;
int descriptorOptimizationType;
int optimizationType;
};
static void icvCreateGLCM_LookupTable_8u_C1R( const uchar* srcImageData, int srcImageStep,
CvSize srcImageSize, CvGLCM* destGLCM,
int* steps, int numSteps, int* memorySteps );
static void
icvCreateGLCMDescriptors_AllowDoubleNest( CvGLCM* destGLCM, int matrixIndex );
CV_IMPL CvGLCM*
cvCreateGLCM( const IplImage* srcImage,
int stepMagnitude,
const int* srcStepDirections,/* should be static array..
or if not the user should handle de-allocation */
int numStepDirections,
int optimizationType )
{
static const int defaultStepDirections[] = { 0,1, -1,1, -1,0, -1,-1 };
int* memorySteps = 0;
CvGLCM* newGLCM = 0;
int* stepDirections = 0;
CV_FUNCNAME( "cvCreateGLCM" );
__BEGIN__;
uchar* srcImageData = 0;
CvSize srcImageSize;
int srcImageStep;
int stepLoop;
const int maxNumGreyLevels8u = CV_MAX_NUM_GREY_LEVELS_8U;
if( !srcImage )
CV_ERROR( CV_StsNullPtr, "" );
if( srcImage->nChannels != 1 )
CV_ERROR( CV_BadNumChannels, "Number of channels must be 1");
if( srcImage->depth != IPL_DEPTH_8U )
CV_ERROR( CV_BadDepth, "Depth must be equal IPL_DEPTH_8U");
// no Directions provided, use the default ones - 0 deg, 45, 90, 135
if( !srcStepDirections )
{
srcStepDirections = defaultStepDirections;
}
CV_CALL( stepDirections = (int*)cvAlloc( numStepDirections*2*sizeof(stepDirections[0])));
memcpy( stepDirections, srcStepDirections, numStepDirections*2*sizeof(stepDirections[0]));
cvGetImageRawData( srcImage, &srcImageData, &srcImageStep, &srcImageSize );
// roll together Directions and magnitudes together with knowledge of image (step)
CV_CALL( memorySteps = (int*)cvAlloc( numStepDirections*sizeof(memorySteps[0])));
for( stepLoop = 0; stepLoop < numStepDirections; stepLoop++ )
{
stepDirections[stepLoop*2 + 0] *= stepMagnitude;
stepDirections[stepLoop*2 + 1] *= stepMagnitude;
memorySteps[stepLoop] = stepDirections[stepLoop*2 + 0]*srcImageStep +
stepDirections[stepLoop*2 + 1];
}
CV_CALL( newGLCM = (CvGLCM*)cvAlloc(sizeof(newGLCM)));
memset( newGLCM, 0, sizeof(newGLCM) );
newGLCM->matrices = 0;
newGLCM->numMatrices = numStepDirections;
newGLCM->optimizationType = optimizationType;
if( optimizationType <= CV_GLCM_OPTIMIZATION_LUT )
{
int lookupTableLoop, imageColLoop, imageRowLoop, lineOffset = 0;
// if optimization type is set to lut, then make one for the image
if( optimizationType == CV_GLCM_OPTIMIZATION_LUT )
{
for( imageRowLoop = 0; imageRowLoop < srcImageSize.height;
imageRowLoop++, lineOffset += srcImageStep )
{
for( imageColLoop = 0; imageColLoop < srcImageSize.width; imageColLoop++ )
{
newGLCM->forwardLookupTable[srcImageData[lineOffset+imageColLoop]]=1;
}
}
newGLCM->numLookupTableElements = 0;
for( lookupTableLoop = 0; lookupTableLoop < maxNumGreyLevels8u; lookupTableLoop++ )
{
if( newGLCM->forwardLookupTable[ lookupTableLoop ] != 0 )
{
newGLCM->forwardLookupTable[ lookupTableLoop ] =
newGLCM->numLookupTableElements;
newGLCM->reverseLookupTable[ newGLCM->numLookupTableElements ] =
lookupTableLoop;
newGLCM->numLookupTableElements++;
}
}
}
// otherwise make a "LUT" which contains all the gray-levels (for code-reuse)
else if( optimizationType == CV_GLCM_OPTIMIZATION_NONE )
{
for( lookupTableLoop = 0; lookupTableLoop <maxNumGreyLevels8u; lookupTableLoop++ )
{
newGLCM->forwardLookupTable[ lookupTableLoop ] = lookupTableLoop;
newGLCM->reverseLookupTable[ lookupTableLoop ] = lookupTableLoop;
}
newGLCM->numLookupTableElements = maxNumGreyLevels8u;
}
newGLCM->matrixSideLength = newGLCM->numLookupTableElements;
icvCreateGLCM_LookupTable_8u_C1R( srcImageData, srcImageStep, srcImageSize,
newGLCM, stepDirections,
numStepDirections, memorySteps );
}
else if( optimizationType == CV_GLCM_OPTIMIZATION_HISTOGRAM )
{
CV_ERROR( CV_StsBadFlag, "Histogram-based method is not implemented" );
/* newGLCM->numMatrices *= 2;
newGLCM->matrixSideLength = maxNumGreyLevels8u*2;
icvCreateGLCM_Histogram_8uC1R( srcImageStep, srcImageSize, srcImageData,
newGLCM, numStepDirections,
stepDirections, memorySteps );
*/
}
__END__;
cvFree( &memorySteps );
cvFree( &stepDirections );
if( cvGetErrStatus() < 0 )
{
cvFree( &newGLCM );
}
return newGLCM;
}
CV_IMPL void
cvReleaseGLCM( CvGLCM** GLCM, int flag )
{
CV_FUNCNAME( "cvReleaseGLCM" );
__BEGIN__;
int matrixLoop;
if( !GLCM )
CV_ERROR( CV_StsNullPtr, "" );
if( *GLCM )
EXIT; // repeated deallocation: just skip it.
if( (flag == CV_GLCM_GLCM || flag == CV_GLCM_ALL) && (*GLCM)->matrices )
{
for( matrixLoop = 0; matrixLoop < (*GLCM)->numMatrices; matrixLoop++ )
{
if( (*GLCM)->matrices[ matrixLoop ] )
{
cvFree( (*GLCM)->matrices[matrixLoop] );
cvFree( (*GLCM)->matrices + matrixLoop );
}
}
cvFree( &((*GLCM)->matrices) );
}
if( (flag == CV_GLCM_DESC || flag == CV_GLCM_ALL) && (*GLCM)->descriptors )
{
for( matrixLoop = 0; matrixLoop < (*GLCM)->numMatrices; matrixLoop++ )
{
cvFree( (*GLCM)->descriptors + matrixLoop );
}
cvFree( &((*GLCM)->descriptors) );
}
if( flag == CV_GLCM_ALL )
{
cvFree( GLCM );
}
__END__;
}
static void
icvCreateGLCM_LookupTable_8u_C1R( const uchar* srcImageData,
int srcImageStep,
CvSize srcImageSize,
CvGLCM* destGLCM,
int* steps,
int numSteps,
int* memorySteps )
{
int* stepIncrementsCounter = 0;
CV_FUNCNAME( "icvCreateGLCM_LookupTable_8u_C1R" );
__BEGIN__;
int matrixSideLength = destGLCM->matrixSideLength;
int stepLoop, sideLoop1, sideLoop2;
int colLoop, rowLoop, lineOffset = 0;
double*** matrices = 0;
// allocate memory to the matrices
CV_CALL( destGLCM->matrices = (double***)cvAlloc( sizeof(matrices[0])*numSteps ));
matrices = destGLCM->matrices;
for( stepLoop=0; stepLoop<numSteps; stepLoop++ )
{
CV_CALL( matrices[stepLoop] = (double**)cvAlloc( sizeof(matrices[0])*matrixSideLength ));
CV_CALL( matrices[stepLoop][0] = (double*)cvAlloc( sizeof(matrices[0][0])*
matrixSideLength*matrixSideLength ));
memset( matrices[stepLoop][0], 0, matrixSideLength*matrixSideLength*
sizeof(matrices[0][0]) );
for( sideLoop1 = 1; sideLoop1 < matrixSideLength; sideLoop1++ )
{
matrices[stepLoop][sideLoop1] = matrices[stepLoop][sideLoop1-1] + matrixSideLength;
}
}
CV_CALL( stepIncrementsCounter = (int*)cvAlloc( numSteps*sizeof(stepIncrementsCounter[0])));
memset( stepIncrementsCounter, 0, numSteps*sizeof(stepIncrementsCounter[0]) );
// generate GLCM for each step
for( rowLoop=0; rowLoop<srcImageSize.height; rowLoop++, lineOffset+=srcImageStep )
{
for( colLoop=0; colLoop<srcImageSize.width; colLoop++ )
{
int pixelValue1 = destGLCM->forwardLookupTable[srcImageData[lineOffset + colLoop]];
for( stepLoop=0; stepLoop<numSteps; stepLoop++ )
{
int col2, row2;
row2 = rowLoop + steps[stepLoop*2 + 0];
col2 = colLoop + steps[stepLoop*2 + 1];
if( col2>=0 && row2>=0 && col2<srcImageSize.width && row2<srcImageSize.height )
{
int memoryStep = memorySteps[ stepLoop ];
int pixelValue2 = destGLCM->forwardLookupTable[ srcImageData[ lineOffset + colLoop + memoryStep ] ];
// maintain symmetry
matrices[stepLoop][pixelValue1][pixelValue2] ++;
matrices[stepLoop][pixelValue2][pixelValue1] ++;
// incremenet counter of total number of increments
stepIncrementsCounter[stepLoop] += 2;
}
}
}
}
// normalize matrices. each element is a probability of gray value i,j adjacency in direction/magnitude k
for( sideLoop1=0; sideLoop1<matrixSideLength; sideLoop1++ )
{
for( sideLoop2=0; sideLoop2<matrixSideLength; sideLoop2++ )
{
for( stepLoop=0; stepLoop<numSteps; stepLoop++ )
{
matrices[stepLoop][sideLoop1][sideLoop2] /= double(stepIncrementsCounter[stepLoop]);
}
}
}
destGLCM->matrices = matrices;
__END__;
cvFree( &stepIncrementsCounter );
if( cvGetErrStatus() < 0 )
cvReleaseGLCM( &destGLCM, CV_GLCM_GLCM );
}
CV_IMPL void
cvCreateGLCMDescriptors( CvGLCM* destGLCM, int descriptorOptimizationType )
{
CV_FUNCNAME( "cvCreateGLCMDescriptors" );
__BEGIN__;
int matrixLoop;
if( !destGLCM )
CV_ERROR( CV_StsNullPtr, "" );
if( !(destGLCM->matrices) )
CV_ERROR( CV_StsNullPtr, "Matrices are not allocated" );
CV_CALL( cvReleaseGLCM( &destGLCM, CV_GLCM_DESC ));
if( destGLCM->optimizationType != CV_GLCM_OPTIMIZATION_HISTOGRAM )
{
destGLCM->descriptorOptimizationType = destGLCM->numDescriptors = descriptorOptimizationType;
}
else
{
CV_ERROR( CV_StsBadFlag, "Histogram-based method is not implemented" );
// destGLCM->descriptorOptimizationType = destGLCM->numDescriptors = CV_GLCMDESC_OPTIMIZATION_HISTOGRAM;
}
CV_CALL( destGLCM->descriptors = (double**)
cvAlloc( destGLCM->numMatrices*sizeof(destGLCM->descriptors[0])));
for( matrixLoop = 0; matrixLoop < destGLCM->numMatrices; matrixLoop ++ )
{
CV_CALL( destGLCM->descriptors[ matrixLoop ] =
(double*)cvAlloc( destGLCM->numDescriptors*sizeof(destGLCM->descriptors[0][0])));
memset( destGLCM->descriptors[matrixLoop], 0, destGLCM->numDescriptors*sizeof(double) );
switch( destGLCM->descriptorOptimizationType )
{
case CV_GLCMDESC_OPTIMIZATION_ALLOWDOUBLENEST:
icvCreateGLCMDescriptors_AllowDoubleNest( destGLCM, matrixLoop );
break;
default:
CV_ERROR( CV_StsBadFlag,
"descriptorOptimizationType different from CV_GLCMDESC_OPTIMIZATION_ALLOWDOUBLENEST\n"
"is not supported" );
/*
case CV_GLCMDESC_OPTIMIZATION_ALLOWTRIPLENEST:
icvCreateGLCMDescriptors_AllowTripleNest( destGLCM, matrixLoop );
break;
case CV_GLCMDESC_OPTIMIZATION_HISTOGRAM:
if(matrixLoop < destGLCM->numMatrices>>1)
icvCreateGLCMDescriptors_Histogram( destGLCM, matrixLoop);
break;
*/
}
}
__END__;
if( cvGetErrStatus() < 0 )
cvReleaseGLCM( &destGLCM, CV_GLCM_DESC );
}
static void
icvCreateGLCMDescriptors_AllowDoubleNest( CvGLCM* destGLCM, int matrixIndex )
{
int sideLoop1, sideLoop2;
int matrixSideLength = destGLCM->matrixSideLength;
double** matrix = destGLCM->matrices[ matrixIndex ];
double* descriptors = destGLCM->descriptors[ matrixIndex ];
double* marginalProbability =
(double*)cvAlloc( matrixSideLength * sizeof(marginalProbability[0]));
memset( marginalProbability, 0, matrixSideLength * sizeof(double) );
double maximumProbability = 0;
double marginalProbabilityEntropy = 0;
double correlationMean = 0, correlationStdDeviation = 0, correlationProductTerm = 0;
for( sideLoop1=0; sideLoop1<matrixSideLength; sideLoop1++ )
{
int actualSideLoop1 = destGLCM->reverseLookupTable[ sideLoop1 ];
for( sideLoop2=0; sideLoop2<matrixSideLength; sideLoop2++ )
{
double entryValue = matrix[ sideLoop1 ][ sideLoop2 ];
int actualSideLoop2 = destGLCM->reverseLookupTable[ sideLoop2 ];
int sideLoopDifference = actualSideLoop1 - actualSideLoop2;
int sideLoopDifferenceSquared = sideLoopDifference*sideLoopDifference;
marginalProbability[ sideLoop1 ] += entryValue;
correlationMean += actualSideLoop1*entryValue;
maximumProbability = MAX( maximumProbability, entryValue );
if( actualSideLoop2 > actualSideLoop1 )
{
descriptors[ CV_GLCMDESC_CONTRAST ] += sideLoopDifferenceSquared * entryValue;
}
descriptors[ CV_GLCMDESC_HOMOGENITY ] += entryValue / ( 1.0 + sideLoopDifferenceSquared );
if( entryValue > 0 )
{
descriptors[ CV_GLCMDESC_ENTROPY ] += entryValue * log( entryValue );
}
descriptors[ CV_GLCMDESC_ENERGY ] += entryValue*entryValue;
}
if( marginalProbability>0 )
marginalProbabilityEntropy += marginalProbability[ actualSideLoop1 ]*log(marginalProbability[ actualSideLoop1 ]);
}
marginalProbabilityEntropy = -marginalProbabilityEntropy;
descriptors[ CV_GLCMDESC_CONTRAST ] += descriptors[ CV_GLCMDESC_CONTRAST ];
descriptors[ CV_GLCMDESC_ENTROPY ] = -descriptors[ CV_GLCMDESC_ENTROPY ];
descriptors[ CV_GLCMDESC_MAXIMUMPROBABILITY ] = maximumProbability;
double HXY = 0, HXY1 = 0, HXY2 = 0;
HXY = descriptors[ CV_GLCMDESC_ENTROPY ];
for( sideLoop1=0; sideLoop1<matrixSideLength; sideLoop1++ )
{
double sideEntryValueSum = 0;
int actualSideLoop1 = destGLCM->reverseLookupTable[ sideLoop1 ];
for( sideLoop2=0; sideLoop2<matrixSideLength; sideLoop2++ )
{
double entryValue = matrix[ sideLoop1 ][ sideLoop2 ];
sideEntryValueSum += entryValue;
int actualSideLoop2 = destGLCM->reverseLookupTable[ sideLoop2 ];
correlationProductTerm += (actualSideLoop1 - correlationMean) * (actualSideLoop2 - correlationMean) * entryValue;
double clusterTerm = actualSideLoop1 + actualSideLoop2 - correlationMean - correlationMean;
descriptors[ CV_GLCMDESC_CLUSTERTENDENCY ] += clusterTerm * clusterTerm * entryValue;
descriptors[ CV_GLCMDESC_CLUSTERSHADE ] += clusterTerm * clusterTerm * clusterTerm * entryValue;
double HXYValue = marginalProbability[ actualSideLoop1 ] * marginalProbability[ actualSideLoop2 ];
if( HXYValue>0 )
{
double HXYValueLog = log( HXYValue );
HXY1 += entryValue * HXYValueLog;
HXY2 += HXYValue * HXYValueLog;
}
}
correlationStdDeviation += (actualSideLoop1-correlationMean) * (actualSideLoop1-correlationMean) * sideEntryValueSum;
}
HXY1 =- HXY1;
HXY2 =- HXY2;
descriptors[ CV_GLCMDESC_CORRELATIONINFO1 ] = ( HXY - HXY1 ) / ( correlationMean );
descriptors[ CV_GLCMDESC_CORRELATIONINFO2 ] = sqrt( 1.0 - exp( -2.0 * (HXY2 - HXY ) ) );
correlationStdDeviation = sqrt( correlationStdDeviation );
descriptors[ CV_GLCMDESC_CORRELATION ] = correlationProductTerm / (correlationStdDeviation*correlationStdDeviation );
delete [] marginalProbability;
}
CV_IMPL double cvGetGLCMDescriptor( CvGLCM* GLCM, int step, int descriptor )
{
double value = DBL_MAX;
CV_FUNCNAME( "cvGetGLCMDescriptor" );
__BEGIN__;
if( !GLCM )
CV_ERROR( CV_StsNullPtr, "" );
if( !(GLCM->descriptors) )
CV_ERROR( CV_StsNullPtr, "" );
if( (unsigned)step >= (unsigned)(GLCM->numMatrices))
CV_ERROR( CV_StsOutOfRange, "step is not in 0 .. GLCM->numMatrices - 1" );
if( (unsigned)descriptor >= (unsigned)(GLCM->numDescriptors))
CV_ERROR( CV_StsOutOfRange, "descriptor is not in 0 .. GLCM->numDescriptors - 1" );
value = GLCM->descriptors[step][descriptor];
__END__;
return value;
}
CV_IMPL void
cvGetGLCMDescriptorStatistics( CvGLCM* GLCM, int descriptor,
double* _average, double* _standardDeviation )
{
CV_FUNCNAME( "cvGetGLCMDescriptorStatistics" );
if( _average )
*_average = DBL_MAX;
if( _standardDeviation )
*_standardDeviation = DBL_MAX;
__BEGIN__;
int matrixLoop, numMatrices;
double average = 0, squareSum = 0;
if( !GLCM )
CV_ERROR( CV_StsNullPtr, "" );
if( !(GLCM->descriptors))
CV_ERROR( CV_StsNullPtr, "Descriptors are not calculated" );
if( (unsigned)descriptor >= (unsigned)(GLCM->numDescriptors) )
CV_ERROR( CV_StsOutOfRange, "Descriptor index is out of range" );
numMatrices = GLCM->numMatrices;
for( matrixLoop = 0; matrixLoop < numMatrices; matrixLoop++ )
{
double temp = GLCM->descriptors[ matrixLoop ][ descriptor ];
average += temp;
squareSum += temp*temp;
}
average /= numMatrices;
if( _average )
*_average = average;
if( _standardDeviation )
*_standardDeviation = sqrt( (squareSum - average*average*numMatrices)/(numMatrices-1));
__END__;
}
CV_IMPL IplImage*
cvCreateGLCMImage( CvGLCM* GLCM, int step )
{
IplImage* dest = 0;
CV_FUNCNAME( "cvCreateGLCMImage" );
__BEGIN__;
float* destData;
int sideLoop1, sideLoop2;
if( !GLCM )
CV_ERROR( CV_StsNullPtr, "" );
if( !(GLCM->matrices) )
CV_ERROR( CV_StsNullPtr, "Matrices are not allocated" );
if( (unsigned)step >= (unsigned)(GLCM->numMatrices) )
CV_ERROR( CV_StsOutOfRange, "The step index is out of range" );
dest = cvCreateImage( cvSize( GLCM->matrixSideLength, GLCM->matrixSideLength ), IPL_DEPTH_32F, 1 );
destData = (float*)(dest->imageData);
for( sideLoop1 = 0; sideLoop1 < GLCM->matrixSideLength;
sideLoop1++, (float*&)destData += dest->widthStep )
{
for( sideLoop2=0; sideLoop2 < GLCM->matrixSideLength; sideLoop2++ )
{
double matrixValue = GLCM->matrices[step][sideLoop1][sideLoop2];
destData[ sideLoop2 ] = (float)matrixValue;
}
}
__END__;
if( cvGetErrStatus() < 0 )
cvReleaseImage( &dest );
return dest;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,975 @@
/*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*/
/****************************************************************************************\
Contour-based face feature tracking
The code was created by Tatiana Cherepanova (tata@sl.iae.nsk.su)
\****************************************************************************************/
#include "precomp.hpp"
#include "_vectrack.h"
#define _ASSERT assert
#define NUM_FACE_ELEMENTS 3
enum
{
MOUTH = 0,
LEYE = 1,
REYE = 2,
};
#define MAX_LAYERS 64
const double pi = 3.1415926535;
struct CvFaceTracker;
struct CvTrackingRect;
class CvFaceElement;
void ThresholdingParam(IplImage *imgGray, int iNumLayers, int &iMinLevel, int &iMaxLevel, float &step, float& power, int iHistMin /*= HIST_MIN*/);
int ChoiceTrackingFace3(CvFaceTracker* pTF, const int nElements, const CvFaceElement* big_face, CvTrackingRect* face, int& new_energy);
int ChoiceTrackingFace2(CvFaceTracker* pTF, const int nElements, const CvFaceElement* big_face, CvTrackingRect* face, int& new_energy, int noel);
inline int GetEnergy(CvTrackingRect** ppNew, const CvTrackingRect* pPrev, CvPoint* ptTempl, CvRect* rTempl);
inline int GetEnergy2(CvTrackingRect** ppNew, const CvTrackingRect* pPrev, CvPoint* ptTempl, CvRect* rTempl, int* element);
inline double CalculateTransformationLMS3_0( CvPoint* pTemplPoints, CvPoint* pSrcPoints);
inline double CalculateTransformationLMS3( CvPoint* pTemplPoints,
CvPoint* pSrcPoints,
double* pdbAverageScale,
double* pdbAverageRotate,
double* pdbAverageShiftX,
double* pdbAverageShiftY );
struct CvTrackingRect
{
CvRect r;
CvPoint ptCenter;
int iColor;
int iEnergy;
int nRectsInThis;
int nRectsOnLeft;
int nRectsOnRight;
int nRectsOnTop;
int nRectsOnBottom;
CvTrackingRect() { memset(this, 0, sizeof(CvTrackingRect)); };
int Energy(const CvTrackingRect& prev)
{
int prev_color = 0 == prev.iColor ? iColor : prev.iColor;
iEnergy = 1 * pow2(r.width - prev.r.width) +
1 * pow2(r.height - prev.r.height) +
1 * pow2(iColor - prev_color) / 4 +
- 1 * nRectsInThis +
- 0 * nRectsOnTop +
+ 0 * nRectsOnLeft +
+ 0 * nRectsOnRight +
+ 0 * nRectsOnBottom;
return iEnergy;
}
};
struct CvFaceTracker
{
CvTrackingRect face[NUM_FACE_ELEMENTS];
int iTrackingFaceType;
double dbRotateDelta;
double dbRotateAngle;
CvPoint ptRotate;
CvPoint ptTempl[NUM_FACE_ELEMENTS];
CvRect rTempl[NUM_FACE_ELEMENTS];
IplImage* imgGray;
IplImage* imgThresh;
CvMemStorage* mstgContours;
CvFaceTracker()
{
ptRotate.x = 0;
ptRotate.y = 0;
dbRotateDelta = 0;
dbRotateAngle = 0;
iTrackingFaceType = -1;
imgThresh = NULL;
imgGray = NULL;
mstgContours = NULL;
};
~CvFaceTracker()
{
if (NULL != imgGray)
delete imgGray;
if (NULL != imgThresh)
delete imgThresh;
if (NULL != mstgContours)
cvReleaseMemStorage(&mstgContours);
};
int Init(CvRect* pRects, IplImage* imgGray)
{
for (int i = 0; i < NUM_FACE_ELEMENTS; i++)
{
face[i].r = pRects[i];
face[i].ptCenter = Center(face[i].r);
ptTempl[i] = face[i].ptCenter;
rTempl[i] = face[i].r;
}
imgGray = cvCreateImage(cvSize(imgGray->width, imgGray->height), 8, 1);
imgThresh = cvCreateImage(cvSize(imgGray->width, imgGray->height), 8, 1);
mstgContours = cvCreateMemStorage();
if ((NULL == imgGray) ||
(NULL == imgThresh) ||
(NULL == mstgContours))
return FALSE;
return TRUE;
};
int InitNextImage(IplImage* img)
{
CvSize sz = {img->width, img->height};
ReallocImage(&imgGray, sz, 1);
ReallocImage(&imgThresh, sz, 1);
ptRotate = face[MOUTH].ptCenter;
float m[6];
CvMat mat = cvMat( 2, 3, CV_32FC1, m );
if (NULL == imgGray || NULL == imgThresh)
return FALSE;
/*m[0] = (float)cos(-dbRotateAngle*CV_PI/180.);
m[1] = (float)sin(-dbRotateAngle*CV_PI/180.);
m[2] = (float)ptRotate.x;
m[3] = -m[1];
m[4] = m[0];
m[5] = (float)ptRotate.y;*/
cv2DRotationMatrix( cvPointTo32f(ptRotate), -dbRotateAngle, 1., &mat );
cvWarpAffine( img, imgGray, &mat );
if (NULL == mstgContours)
mstgContours = cvCreateMemStorage();
else
cvClearMemStorage(mstgContours);
if (NULL == mstgContours)
return FALSE;
return TRUE;
}
};
class CvFaceElement
{
public:
CvSeq* m_seqRects;
CvMemStorage* m_mstgRects;
CvRect m_rROI;
CvTrackingRect m_trPrev;
inline CvFaceElement()
{
m_seqRects = NULL;
m_mstgRects = NULL;
m_rROI.x = 0;
m_rROI.y = 0;
m_rROI.width = 0;
m_rROI.height = 0;
};
inline int Init(const CvRect& roi, const CvTrackingRect& prev, CvMemStorage* mstg = NULL)
{
m_rROI = roi;
m_trPrev = prev;
if (NULL != mstg)
m_mstgRects = mstg;
if (NULL == m_mstgRects)
return FALSE;
if (NULL == m_seqRects)
m_seqRects = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvTrackingRect), m_mstgRects);
else
cvClearSeq(m_seqRects);
if (NULL == m_seqRects)
return FALSE;
return TRUE;
};
void FindRects(IplImage* img, IplImage* thresh, int nLayers, int dMinSize);
protected:
void FindContours(IplImage* img, IplImage* thresh, int nLayers, int dMinSize);
void MergeRects(int d);
void Energy();
}; //class CvFaceElement
int CV_CDECL CompareEnergy(const void* el1, const void* el2, void*)
{
return ((CvTrackingRect*)el1)->iEnergy - ((CvTrackingRect*)el2)->iEnergy;
}// int CV_CDECL CompareEnergy(const void* el1, const void* el2, void*)
void CvFaceElement::FindRects(IplImage* img, IplImage* thresh, int nLayers, int dMinSize)
{
FindContours(img, thresh, nLayers, dMinSize / 4);
if (0 == m_seqRects->total)
return;
Energy();
cvSeqSort(m_seqRects, CompareEnergy, NULL);
CvTrackingRect* pR = (CvTrackingRect*)cvGetSeqElem(m_seqRects, 0);
if (m_seqRects->total < 32)
{
MergeRects(dMinSize / 8);
Energy();
cvSeqSort(m_seqRects, CompareEnergy, NULL);
}
pR = (CvTrackingRect*)cvGetSeqElem(m_seqRects, 0);
if ((pR->iEnergy > 100 && m_seqRects->total < 32) || (m_seqRects->total < 16))
{
MergeRects(dMinSize / 4);
Energy();
cvSeqSort(m_seqRects, CompareEnergy, NULL);
}
pR = (CvTrackingRect*)cvGetSeqElem(m_seqRects, 0);
if ((pR->iEnergy > 100 && m_seqRects->total < 16) || (pR->iEnergy > 200 && m_seqRects->total < 32))
{
MergeRects(dMinSize / 2);
Energy();
cvSeqSort(m_seqRects, CompareEnergy, NULL);
}
}// void CvFaceElement::FindRects(IplImage* img, IplImage* thresh, int nLayers, int dMinSize)
void CvFaceElement::FindContours(IplImage* img, IplImage* thresh, int nLayers, int dMinSize)
{
CvSeq* seq;
CvRect roi = m_rROI;
Extend(roi, 1);
cvSetImageROI(img, roi);
cvSetImageROI(thresh, roi);
// layers
int colors[MAX_LAYERS] = {0};
int iMinLevel = 0, iMaxLevel = 255;
float step, power;
ThresholdingParam(img, nLayers / 2, iMinLevel, iMaxLevel, step, power, 4);
int iMinLevelPrev = iMinLevel;
int iMaxLevelPrev = iMinLevel;
if (m_trPrev.iColor != 0)
{
iMinLevelPrev = m_trPrev.iColor - nLayers / 2;
iMaxLevelPrev = m_trPrev.iColor + nLayers / 2;
}
if (iMinLevelPrev < iMinLevel)
{
iMaxLevelPrev += iMinLevel - iMinLevelPrev;
iMinLevelPrev = iMinLevel;
}
if (iMaxLevelPrev > iMaxLevel)
{
iMinLevelPrev -= iMaxLevelPrev - iMaxLevel;
if (iMinLevelPrev < iMinLevel)
iMinLevelPrev = iMinLevel;
iMaxLevelPrev = iMaxLevel;
}
int n = nLayers;
n -= (iMaxLevelPrev - iMinLevelPrev + 1) / 2;
step = float(iMinLevelPrev - iMinLevel + iMaxLevel - iMaxLevelPrev) / float(n);
int j = 0;
float level;
for (level = (float)iMinLevel; level < iMinLevelPrev && j < nLayers; level += step, j++)
colors[j] = int(level + 0.5);
for (level = (float)iMinLevelPrev; level < iMaxLevelPrev && j < nLayers; level += 2.0, j++)
colors[j] = int(level + 0.5);
for (level = (float)iMaxLevelPrev; level < iMaxLevel && j < nLayers; level += step, j++)
colors[j] = int(level + 0.5);
//
for (int i = 0; i < nLayers; i++)
{
cvThreshold(img, thresh, colors[i], 255.0, CV_THRESH_BINARY);
if (cvFindContours(thresh, m_mstgRects, &seq, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE))
{
CvTrackingRect cr;
for (CvSeq* external = seq; external; external = external->h_next)
{
cr.r = cvContourBoundingRect(external);
Move(cr.r, roi.x, roi.y);
if (RectInRect(cr.r, m_rROI) && cr.r.width > dMinSize && cr.r.height > dMinSize)
{
cr.ptCenter = Center(cr.r);
cr.iColor = colors[i];
cvSeqPush(m_seqRects, &cr);
}
for (CvSeq* internal = external->v_next; internal; internal = internal->h_next)
{
cr.r = cvContourBoundingRect(internal);
Move(cr.r, roi.x, roi.y);
if (RectInRect(cr.r, m_rROI) && cr.r.width > dMinSize && cr.r.height > dMinSize)
{
cr.ptCenter = Center(cr.r);
cr.iColor = colors[i];
cvSeqPush(m_seqRects, &cr);
}
}
}
cvClearSeq(seq);
}
}
cvResetImageROI(img);
cvResetImageROI(thresh);
}//void CvFaceElement::FindContours(IplImage* img, IplImage* thresh, int nLayers)
void CvFaceElement::MergeRects(int d)
{
int nRects = m_seqRects->total;
CvSeqReader reader, reader2;
cvStartReadSeq( m_seqRects, &reader );
int i, j;
for (i = 0; i < nRects; i++)
{
CvTrackingRect* pRect1 = (CvTrackingRect*)(reader.ptr);
cvStartReadSeq( m_seqRects, &reader2 );
cvSetSeqReaderPos(&reader2, i + 1);
for (j = i + 1; j < nRects; j++)
{
CvTrackingRect* pRect2 = (CvTrackingRect*)(reader2.ptr);
if (abs(pRect1->ptCenter.y - pRect2->ptCenter.y) < d &&
abs(pRect1->r.height - pRect2->r.height) < d)
{
CvTrackingRect rNew;
rNew.iColor = (pRect1->iColor + pRect2->iColor + 1) / 2;
rNew.r.x = min(pRect1->r.x, pRect2->r.x);
rNew.r.y = min(pRect1->r.y, pRect2->r.y);
rNew.r.width = max(pRect1->r.x + pRect1->r.width, pRect2->r.x + pRect2->r.width) - rNew.r.x;
rNew.r.height = min(pRect1->r.y + pRect1->r.height, pRect2->r.y + pRect2->r.height) - rNew.r.y;
if (rNew.r != pRect1->r && rNew.r != pRect2->r)
{
rNew.ptCenter = Center(rNew.r);
cvSeqPush(m_seqRects, &rNew);
}
}
CV_NEXT_SEQ_ELEM( sizeof(CvTrackingRect), reader2 );
}
CV_NEXT_SEQ_ELEM( sizeof(CvTrackingRect), reader );
}
// delete equal rects
for (i = 0; i < m_seqRects->total; i++)
{
CvTrackingRect* pRect1 = (CvTrackingRect*)cvGetSeqElem(m_seqRects, i);
int j_begin = i + 1;
for (j = j_begin; j < m_seqRects->total;)
{
CvTrackingRect* pRect2 = (CvTrackingRect*)cvGetSeqElem(m_seqRects, j);
if (pRect1->r == pRect2->r)
cvSeqRemove(m_seqRects, j);
else
j++;
}
}
}//void CvFaceElement::MergeRects(int d)
void CvFaceElement::Energy()
{
CvSeqReader reader, reader2;
cvStartReadSeq( m_seqRects, &reader );
for (int i = 0; i < m_seqRects->total; i++)
{
CvTrackingRect* pRect = (CvTrackingRect*)(reader.ptr);
// outside and inside rects
cvStartReadSeq( m_seqRects, &reader2 );
for (int j = 0; j < m_seqRects->total; j++)
{
CvTrackingRect* pRect2 = (CvTrackingRect*)(reader2.ptr);
if (i != j)
{
if (RectInRect(pRect2->r, pRect->r))
pRect->nRectsInThis ++;
else if (pRect2->r.y + pRect2->r.height <= pRect->r.y)
pRect->nRectsOnTop ++;
else if (pRect2->r.y >= pRect->r.y + pRect->r.height)
pRect->nRectsOnBottom ++;
else if (pRect2->r.x + pRect2->r.width <= pRect->r.x)
pRect->nRectsOnLeft ++;
else if (pRect2->r.x >= pRect->r.x + pRect->r.width)
pRect->nRectsOnRight ++;
}
CV_NEXT_SEQ_ELEM( sizeof(CvTrackingRect), reader2 );
}
// energy
pRect->Energy(m_trPrev);
CV_NEXT_SEQ_ELEM( sizeof(CvTrackingRect), reader );
}
}//void CvFaceElement::Energy()
CV_IMPL CvFaceTracker*
cvInitFaceTracker(CvFaceTracker* pFaceTracker, const IplImage* imgGray, CvRect* pRects, int nRects)
{
_ASSERT(NULL != imgGray);
_ASSERT(NULL != pRects);
_ASSERT(nRects >= NUM_FACE_ELEMENTS);
if ((NULL == imgGray) ||
(NULL == pRects) ||
(nRects < NUM_FACE_ELEMENTS))
return NULL;
int new_face = FALSE;
CvFaceTracker* pFace = pFaceTracker;
if (NULL == pFace)
{
pFace = new CvFaceTracker;
if (NULL == pFace)
return NULL;
new_face = TRUE;
}
pFace->Init(pRects, (IplImage*)imgGray);
return pFace;
}//CvFaceTracker* InitFaceTracker(IplImage* imgGray, CvRect* pRects, int nRects)
CV_IMPL void
cvReleaseFaceTracker(CvFaceTracker** ppFaceTracker)
{
if (NULL == *ppFaceTracker)
return;
delete *ppFaceTracker;
*ppFaceTracker = NULL;
}//void ReleaseFaceTracker(CvFaceTracker** ppFaceTracker)
CV_IMPL int
cvTrackFace(CvFaceTracker* pFaceTracker, IplImage* imgGray, CvRect* pRects, int nRects, CvPoint* ptRotate, double* dbAngleRotate)
{
_ASSERT(NULL != pFaceTracker);
_ASSERT(NULL != imgGray);
_ASSERT(NULL != pRects && nRects >= NUM_FACE_ELEMENTS);
if ((NULL == pFaceTracker) ||
(NULL == imgGray))
return FALSE;
pFaceTracker->InitNextImage(imgGray);
*ptRotate = pFaceTracker->ptRotate;
*dbAngleRotate = pFaceTracker->dbRotateAngle;
int nElements = 16;
double dx = pFaceTracker->face[LEYE].ptCenter.x - pFaceTracker->face[REYE].ptCenter.x;
double dy = pFaceTracker->face[LEYE].ptCenter.y - pFaceTracker->face[REYE].ptCenter.y;
double d_eyes = sqrt(dx*dx + dy*dy);
int d = cvRound(0.25 * d_eyes);
int dMinSize = d;
int nRestarts = 0;
int elem;
CvFaceElement big_face[NUM_FACE_ELEMENTS];
START:
// init
for (elem = 0; elem < NUM_FACE_ELEMENTS; elem++)
{
CvRect r = pFaceTracker->face[elem].r;
Extend(r, d);
if (r.width < 4*d)
{
r.x -= (4*d - r.width) / 2;
r.width += 4*d - r.width;
}
if (r.height < 3*d)
{
r.y -= (3*d - r.height) / 2;
r.height += 3*d - r.height;
}
if (r.x < 1)
r.x = 1;
if (r.y < 1)
r.y = 1;
if (r.x + r.width > pFaceTracker->imgGray->width - 2)
r.width = pFaceTracker->imgGray->width - 2 - r.x;
if (r.y + r.height > pFaceTracker->imgGray->height - 2)
r.height = pFaceTracker->imgGray->height - 2 - r.y;
if (!big_face[elem].Init(r, pFaceTracker->face[elem], pFaceTracker->mstgContours))
return FALSE;
}
// find contours
for (elem = 0; elem < NUM_FACE_ELEMENTS; elem++)
big_face[elem].FindRects(pFaceTracker->imgGray, pFaceTracker->imgThresh, 32, dMinSize);
// candidats
CvTrackingRect new_face[NUM_FACE_ELEMENTS];
int new_energy = 0;
int found = ChoiceTrackingFace3(pFaceTracker, nElements, big_face, new_face, new_energy);
int restart = FALSE;
int find2 = FALSE;
int noel = -1;
if (found)
{
if (new_energy > 100000 && -1 != pFaceTracker->iTrackingFaceType)
find2 = TRUE;
else if (new_energy > 150000)
{
int elements = 0;
for (int el = 0; el < NUM_FACE_ELEMENTS; el++)
{
if (big_face[el].m_seqRects->total > 16 || (big_face[el].m_seqRects->total > 8 && new_face[el].iEnergy < 100))
elements++;
else
noel = el;
}
if (2 == elements)
find2 = TRUE;
else
restart = TRUE;
}
}
else
{
if (-1 != pFaceTracker->iTrackingFaceType)
find2 = TRUE;
else
restart = TRUE;
}
RESTART:
if (restart)
{
if (nRestarts++ < 2)
{
d = d + d/4;
goto START;
}
}
else if (find2)
{
if (-1 != pFaceTracker->iTrackingFaceType)
noel = pFaceTracker->iTrackingFaceType;
int found2 = ChoiceTrackingFace2(pFaceTracker, nElements, big_face, new_face, new_energy, noel);
if (found2 && new_energy < 100000)
{
pFaceTracker->iTrackingFaceType = noel;
found = TRUE;
}
else
{
restart = TRUE;
goto RESTART;
}
}
if (found)
{
// angle by mouth & eyes
double vx_prev = double(pFaceTracker->face[LEYE].ptCenter.x + pFaceTracker->face[REYE].ptCenter.x) / 2.0 - pFaceTracker->face[MOUTH].ptCenter.x;
double vy_prev = double(pFaceTracker->face[LEYE].ptCenter.y + pFaceTracker->face[REYE].ptCenter.y) / 2.0 - pFaceTracker->face[MOUTH].ptCenter.y;
double vx_prev1 = vx_prev * cos(pFaceTracker->dbRotateDelta) - vy_prev * sin(pFaceTracker->dbRotateDelta);
double vy_prev1 = vx_prev * sin(pFaceTracker->dbRotateDelta) + vy_prev * cos(pFaceTracker->dbRotateDelta);
vx_prev = vx_prev1;
vy_prev = vy_prev1;
for (elem = 0; elem < NUM_FACE_ELEMENTS; elem++)
pFaceTracker->face[elem] = new_face[elem];
double vx = double(pFaceTracker->face[LEYE].ptCenter.x + pFaceTracker->face[REYE].ptCenter.x) / 2.0 - pFaceTracker->face[MOUTH].ptCenter.x;
double vy = double(pFaceTracker->face[LEYE].ptCenter.y + pFaceTracker->face[REYE].ptCenter.y) / 2.0 - pFaceTracker->face[MOUTH].ptCenter.y;
pFaceTracker->dbRotateDelta = 0;
double n1_n2 = (vx * vx + vy * vy) * (vx_prev * vx_prev + vy_prev * vy_prev);
if (n1_n2 != 0)
pFaceTracker->dbRotateDelta = asin((vx * vy_prev - vx_prev * vy) / sqrt(n1_n2));
pFaceTracker->dbRotateAngle -= pFaceTracker->dbRotateDelta;
}
else
{
pFaceTracker->dbRotateDelta = 0;
pFaceTracker->dbRotateAngle = 0;
}
if ((pFaceTracker->dbRotateAngle >= pi/2 && pFaceTracker->dbRotateAngle > 0) ||
(pFaceTracker->dbRotateAngle <= -pi/2 && pFaceTracker->dbRotateAngle < 0))
{
pFaceTracker->dbRotateDelta = 0;
pFaceTracker->dbRotateAngle = 0;
found = FALSE;
}
if (found)
{
for (int i = 0; i < NUM_FACE_ELEMENTS && i < nRects; i++)
pRects[i] = pFaceTracker->face[i].r;
}
return found;
}//int FindFaceTracker(CvFaceTracker* pFaceTracker, IplImage* imgGray, CvRect* pRects, int nRects, CvPoint& ptRotate, double& dbAngleRotate)
void ThresholdingParam(IplImage *imgGray, int iNumLayers, int &iMinLevel, int &iMaxLevel, float &step, float& power, int iHistMin /*= HIST_MIN*/)
{
_ASSERT(imgGray != NULL);
_ASSERT(imgGray->nChannels == 1);
int i, j;
// create histogram
int histImg[256] = {0};
uchar* buffImg = (uchar*)imgGray->imageData;
CvRect rROI = cvGetImageROI(imgGray);
buffImg += rROI.y * imgGray->widthStep + rROI.x;
for (j = 0; j < rROI.height; j++)
{
for (i = 0; i < rROI.width; i++)
histImg[buffImg[i]] ++;
buffImg += imgGray->widthStep;
}
// params
for (i = 0; i < 256; i++)
{
if (histImg[i] > iHistMin)
break;
}
iMinLevel = i;
for (i = 255; i >= 0; i--)
{
if (histImg[i] > iHistMin)
break;
}
iMaxLevel = i;
if (iMaxLevel <= iMinLevel)
{
iMaxLevel = 255;
iMinLevel = 0;
}
// power
double black = 1;
double white = 1;
for (i = iMinLevel; i < (iMinLevel + iMaxLevel) / 2; i++)
black += histImg[i];
for (i = (iMinLevel + iMaxLevel) / 2; i < iMaxLevel; i++)
white += histImg[i];
power = float(black) / float(2 * white);
//
step = float(iMaxLevel - iMinLevel) / float(iNumLayers);
if (step < 1.0)
step = 1.0;
}// void ThresholdingParam(IplImage *imgGray, int iNumLayers, int &iMinLevel, int &iMaxLevel, int &iStep)
int ChoiceTrackingFace3(CvFaceTracker* pTF, const int nElements, const CvFaceElement* big_face, CvTrackingRect* face, int& new_energy)
{
CvTrackingRect* curr_face[NUM_FACE_ELEMENTS] = {NULL};
CvTrackingRect* new_face[NUM_FACE_ELEMENTS] = {NULL};
new_energy = 0x7fffffff;
int curr_energy = 0x7fffffff;
int found = FALSE;
int N = 0;
CvSeqReader reader_m, reader_l, reader_r;
cvStartReadSeq( big_face[MOUTH].m_seqRects, &reader_m );
for (int i_mouth = 0; i_mouth < big_face[MOUTH].m_seqRects->total && i_mouth < nElements; i_mouth++)
{
curr_face[MOUTH] = (CvTrackingRect*)(reader_m.ptr);
cvStartReadSeq( big_face[LEYE].m_seqRects, &reader_l );
for (int i_left = 0; i_left < big_face[LEYE].m_seqRects->total && i_left < nElements; i_left++)
{
curr_face[LEYE] = (CvTrackingRect*)(reader_l.ptr);
if (curr_face[LEYE]->r.y + curr_face[LEYE]->r.height < curr_face[MOUTH]->r.y)
{
cvStartReadSeq( big_face[REYE].m_seqRects, &reader_r );
for (int i_right = 0; i_right < big_face[REYE].m_seqRects->total && i_right < nElements; i_right++)
{
curr_face[REYE] = (CvTrackingRect*)(reader_r.ptr);
if (curr_face[REYE]->r.y + curr_face[REYE]->r.height < curr_face[MOUTH]->r.y &&
curr_face[REYE]->r.x > curr_face[LEYE]->r.x + curr_face[LEYE]->r.width)
{
curr_energy = GetEnergy(curr_face, pTF->face, pTF->ptTempl, pTF->rTempl);
if (curr_energy < new_energy)
{
for (int elem = 0; elem < NUM_FACE_ELEMENTS; elem++)
new_face[elem] = curr_face[elem];
new_energy = curr_energy;
found = TRUE;
}
N++;
}
}
}
}
}
if (found)
{
for (int elem = 0; elem < NUM_FACE_ELEMENTS; elem++)
face[elem] = *(new_face[elem]);
}
return found;
} // int ChoiceTrackingFace3(const CvTrackingRect* tr_face, CvTrackingRect* new_face, int& new_energy)
int ChoiceTrackingFace2(CvFaceTracker* pTF, const int nElements, const CvFaceElement* big_face, CvTrackingRect* face, int& new_energy, int noel)
{
int element[NUM_FACE_ELEMENTS];
for (int i = 0, elem = 0; i < NUM_FACE_ELEMENTS; i++)
{
if (i != noel)
{
element[elem] = i;
elem ++;
}
else
element[2] = i;
}
CvTrackingRect* curr_face[NUM_FACE_ELEMENTS] = {NULL};
CvTrackingRect* new_face[NUM_FACE_ELEMENTS] = {NULL};
new_energy = 0x7fffffff;
int curr_energy = 0x7fffffff;
int found = FALSE;
int N = 0;
CvSeqReader reader0, reader1;
cvStartReadSeq( big_face[element[0]].m_seqRects, &reader0 );
for (int i0 = 0; i0 < big_face[element[0]].m_seqRects->total && i0 < nElements; i0++)
{
curr_face[element[0]] = (CvTrackingRect*)(reader0.ptr);
cvStartReadSeq( big_face[element[1]].m_seqRects, &reader1 );
for (int i1 = 0; i1 < big_face[element[1]].m_seqRects->total && i1 < nElements; i1++)
{
curr_face[element[1]] = (CvTrackingRect*)(reader1.ptr);
curr_energy = GetEnergy2(curr_face, pTF->face, pTF->ptTempl, pTF->rTempl, element);
if (curr_energy < new_energy)
{
for (int elem = 0; elem < NUM_FACE_ELEMENTS; elem++)
new_face[elem] = curr_face[elem];
new_energy = curr_energy;
found = TRUE;
}
N++;
}
}
if (found)
{
face[element[0]] = *(new_face[element[0]]);
face[element[1]] = *(new_face[element[1]]);
// 3 element find by template
CvPoint templ_v01 = {pTF->ptTempl[element[1]].x - pTF->ptTempl[element[0]].x, pTF->ptTempl[element[1]].y - pTF->ptTempl[element[0]].y};
CvPoint templ_v02 = {pTF->ptTempl[element[2]].x - pTF->ptTempl[element[0]].x, pTF->ptTempl[element[2]].y - pTF->ptTempl[element[0]].y};
CvPoint prev_v01 = {pTF->face[element[1]].ptCenter.x - pTF->face[element[0]].ptCenter.x, pTF->face[element[1]].ptCenter.y - pTF->face[element[0]].ptCenter.y};
CvPoint prev_v02 = {pTF->face[element[2]].ptCenter.x - pTF->face[element[0]].ptCenter.x, pTF->face[element[2]].ptCenter.y - pTF->face[element[0]].ptCenter.y};
CvPoint new_v01 = {new_face[element[1]]->ptCenter.x - new_face[element[0]]->ptCenter.x, new_face[element[1]]->ptCenter.y - new_face[element[0]]->ptCenter.y};
double templ_d01 = sqrt((double)templ_v01.x*templ_v01.x + templ_v01.y*templ_v01.y);
double templ_d02 = sqrt((double)templ_v02.x*templ_v02.x + templ_v02.y*templ_v02.y);
double prev_d01 = sqrt((double)prev_v01.x*prev_v01.x + prev_v01.y*prev_v01.y);
double prev_d02 = sqrt((double)prev_v02.x*prev_v02.x + prev_v02.y*prev_v02.y);
double new_d01 = sqrt((double)new_v01.x*new_v01.x + new_v01.y*new_v01.y);
double scale = templ_d01 / new_d01;
double new_d02 = templ_d02 / scale;
double sin_a = double(prev_v01.x * prev_v02.y - prev_v01.y * prev_v02.x) / (prev_d01 * prev_d02);
double cos_a = cos(asin(sin_a));
double x = double(new_v01.x) * cos_a - double(new_v01.y) * sin_a;
double y = double(new_v01.x) * sin_a + double(new_v01.y) * cos_a;
x = x * new_d02 / new_d01;
y = y * new_d02 / new_d01;
CvPoint new_v02 = {int(x + 0.5), int(y + 0.5)};
face[element[2]].iColor = 0;
face[element[2]].iEnergy = 0;
face[element[2]].nRectsInThis = 0;
face[element[2]].nRectsOnBottom = 0;
face[element[2]].nRectsOnLeft = 0;
face[element[2]].nRectsOnRight = 0;
face[element[2]].nRectsOnTop = 0;
face[element[2]].ptCenter.x = new_v02.x + new_face[element[0]]->ptCenter.x;
face[element[2]].ptCenter.y = new_v02.y + new_face[element[0]]->ptCenter.y;
face[element[2]].r.width = int(double(pTF->rTempl[element[2]].width) / (scale) + 0.5);
face[element[2]].r.height = int(double(pTF->rTempl[element[2]].height) / (scale) + 0.5);
face[element[2]].r.x = face[element[2]].ptCenter.x - (face[element[2]].r.width + 1) / 2;
face[element[2]].r.y = face[element[2]].ptCenter.y - (face[element[2]].r.height + 1) / 2;
_ASSERT(face[LEYE].r.x + face[LEYE].r.width <= face[REYE].r.x);
}
return found;
} // int ChoiceTrackingFace3(const CvTrackingRect* tr_face, CvTrackingRect* new_face, int& new_energy)
inline int GetEnergy(CvTrackingRect** ppNew, const CvTrackingRect* pPrev, CvPoint* ptTempl, CvRect* rTempl)
{
int energy = 0;
CvPoint ptNew[NUM_FACE_ELEMENTS];
CvPoint ptPrev[NUM_FACE_ELEMENTS];
for (int i = 0; i < NUM_FACE_ELEMENTS; i++)
{
ptNew[i] = ppNew[i]->ptCenter;
ptPrev[i] = pPrev[i].ptCenter;
energy += ppNew[i]->iEnergy - 2 * ppNew[i]->nRectsInThis;
}
double dx = 0, dy = 0, scale = 1, rotate = 0;
double e_templ = CalculateTransformationLMS3(ptTempl, ptNew, &scale, &rotate, &dx, &dy);
double e_prev = CalculateTransformationLMS3_0(ptPrev, ptNew);
double w_eye = double(ppNew[LEYE]->r.width + ppNew[REYE]->r.width) * scale / 2.0;
double h_eye = double(ppNew[LEYE]->r.height + ppNew[REYE]->r.height) * scale / 2.0;
double w_mouth = double(ppNew[MOUTH]->r.width) * scale;
double h_mouth = double(ppNew[MOUTH]->r.height) * scale;
energy +=
int(512.0 * (e_prev + 16.0 * e_templ)) +
4 * pow2(ppNew[LEYE]->r.width - ppNew[REYE]->r.width) +
4 * pow2(ppNew[LEYE]->r.height - ppNew[REYE]->r.height) +
4 * (int)pow(w_eye - double(rTempl[LEYE].width + rTempl[REYE].width) / 2.0, 2) +
2 * (int)pow(h_eye - double(rTempl[LEYE].height + rTempl[REYE].height) / 2.0, 2) +
1 * (int)pow(w_mouth - double(rTempl[MOUTH].width), 2) +
1 * (int)pow(h_mouth - double(rTempl[MOUTH].height), 2) +
0;
return energy;
}
inline int GetEnergy2(CvTrackingRect** ppNew, const CvTrackingRect* pPrev, CvPoint* ptTempl, CvRect* rTempl, int* element)
{
CvPoint new_v = {ppNew[element[0]]->ptCenter.x - ppNew[element[1]]->ptCenter.x,
ppNew[element[0]]->ptCenter.y - ppNew[element[1]]->ptCenter.y};
CvPoint prev_v = {pPrev[element[0]].ptCenter.x - pPrev[element[1]].ptCenter.x,
pPrev[element[0]].ptCenter.y - pPrev[element[1]].ptCenter.y};
double new_d = sqrt((double)new_v.x*new_v.x + new_v.y*new_v.y);
double prev_d = sqrt((double)prev_v.x*prev_v.x + prev_v.y*prev_v.y);
double dx = ptTempl[element[0]].x - ptTempl[element[1]].x;
double dy = ptTempl[element[0]].y - ptTempl[element[1]].y;
double templ_d = sqrt(dx*dx + dy*dy);
double scale_templ = new_d / templ_d;
double w0 = (double)ppNew[element[0]]->r.width * scale_templ;
double h0 = (double)ppNew[element[0]]->r.height * scale_templ;
double w1 = (double)ppNew[element[1]]->r.width * scale_templ;
double h1 = (double)ppNew[element[1]]->r.height * scale_templ;
int energy = ppNew[element[0]]->iEnergy + ppNew[element[1]]->iEnergy +
- 2 * (ppNew[element[0]]->nRectsInThis - ppNew[element[1]]->nRectsInThis) +
(int)pow(w0 - (double)rTempl[element[0]].width, 2) +
(int)pow(h0 - (double)rTempl[element[0]].height, 2) +
(int)pow(w1 - (double)rTempl[element[1]].width, 2) +
(int)pow(h1 - (double)rTempl[element[1]].height, 2) +
(int)pow(new_d - prev_d, 2) +
0;
return energy;
}
inline double CalculateTransformationLMS3( CvPoint* pTemplPoints,
CvPoint* pSrcPoints,
double* pdbAverageScale,
double* pdbAverageRotate,
double* pdbAverageShiftX,
double* pdbAverageShiftY )
{
// double WS = 0;
double dbAverageScale = 1;
double dbAverageRotate = 0;
double dbAverageShiftX = 0;
double dbAverageShiftY = 0;
double dbLMS = 0;
_ASSERT( NULL != pTemplPoints);
_ASSERT( NULL != pSrcPoints);
double dbXt = double(pTemplPoints[0].x + pTemplPoints[1].x + pTemplPoints[2].x) / 3.0;
double dbYt = double(pTemplPoints[0].y + pTemplPoints[1].y + pTemplPoints[2].y ) / 3.0;
double dbXs = double(pSrcPoints[0].x + pSrcPoints[1].x + pSrcPoints[2].x) / 3.0;
double dbYs = double(pSrcPoints[0].y + pSrcPoints[1].y + pSrcPoints[2].y) / 3.0;
double dbXtXt = double(pow2(pTemplPoints[0].x) + pow2(pTemplPoints[1].x) + pow2(pTemplPoints[2].x)) / 3.0;
double dbYtYt = double(pow2(pTemplPoints[0].y) + pow2(pTemplPoints[1].y) + pow2(pTemplPoints[2].y)) / 3.0;
double dbXsXs = double(pow2(pSrcPoints[0].x) + pow2(pSrcPoints[1].x) + pow2(pSrcPoints[2].x)) / 3.0;
double dbYsYs = double(pow2(pSrcPoints[0].y) + pow2(pSrcPoints[1].y) + pow2(pSrcPoints[2].y)) / 3.0;
double dbXtXs = double(pTemplPoints[0].x * pSrcPoints[0].x +
pTemplPoints[1].x * pSrcPoints[1].x +
pTemplPoints[2].x * pSrcPoints[2].x) / 3.0;
double dbYtYs = double(pTemplPoints[0].y * pSrcPoints[0].y +
pTemplPoints[1].y * pSrcPoints[1].y +
pTemplPoints[2].y * pSrcPoints[2].y) / 3.0;
double dbXtYs = double(pTemplPoints[0].x * pSrcPoints[0].y +
pTemplPoints[1].x * pSrcPoints[1].y +
pTemplPoints[2].x * pSrcPoints[2].y) / 3.0;
double dbYtXs = double(pTemplPoints[0].y * pSrcPoints[0].x +
pTemplPoints[1].y * pSrcPoints[1].x +
pTemplPoints[2].y * pSrcPoints[2].x ) / 3.0;
dbXtXt -= dbXt * dbXt;
dbYtYt -= dbYt * dbYt;
dbXsXs -= dbXs * dbXs;
dbYsYs -= dbYs * dbYs;
dbXtXs -= dbXt * dbXs;
dbYtYs -= dbYt * dbYs;
dbXtYs -= dbXt * dbYs;
dbYtXs -= dbYt * dbXs;
dbAverageRotate = atan2( dbXtYs - dbYtXs, dbXtXs + dbYtYs );
double cosR = cos(dbAverageRotate);
double sinR = sin(dbAverageRotate);
double del = dbXsXs + dbYsYs;
if( del != 0 )
{
dbAverageScale = (double(dbXtXs + dbYtYs) * cosR + double(dbXtYs - dbYtXs) * sinR) / del;
dbLMS = dbXtXt + dbYtYt - ((double)pow(dbXtXs + dbYtYs,2) + (double)pow(dbXtYs - dbYtXs,2)) / del;
}
dbAverageShiftX = double(dbXt) - dbAverageScale * (double(dbXs) * cosR + double(dbYs) * sinR);
dbAverageShiftY = double(dbYt) - dbAverageScale * (double(dbYs) * cosR - double(dbXs) * sinR);
if( pdbAverageScale != NULL ) *pdbAverageScale = dbAverageScale;
if( pdbAverageRotate != NULL ) *pdbAverageRotate = dbAverageRotate;
if( pdbAverageShiftX != NULL ) *pdbAverageShiftX = dbAverageShiftX;
if( pdbAverageShiftY != NULL ) *pdbAverageShiftY = dbAverageShiftY;
_ASSERT(dbLMS >= 0);
return dbLMS;
}
inline double CalculateTransformationLMS3_0( CvPoint* pTemplPoints, CvPoint* pSrcPoints)
{
double dbLMS = 0;
_ASSERT( NULL != pTemplPoints);
_ASSERT( NULL != pSrcPoints);
double dbXt = double(pTemplPoints[0].x + pTemplPoints[1].x + pTemplPoints[2].x) / 3.0;
double dbYt = double(pTemplPoints[0].y + pTemplPoints[1].y + pTemplPoints[2].y ) / 3.0;
double dbXs = double(pSrcPoints[0].x + pSrcPoints[1].x + pSrcPoints[2].x) / 3.0;
double dbYs = double(pSrcPoints[0].y + pSrcPoints[1].y + pSrcPoints[2].y) / 3.0;
double dbXtXt = double(pow2(pTemplPoints[0].x) + pow2(pTemplPoints[1].x) + pow2(pTemplPoints[2].x)) / 3.0;
double dbYtYt = double(pow2(pTemplPoints[0].y) + pow2(pTemplPoints[1].y) + pow2(pTemplPoints[2].y)) / 3.0;
double dbXsXs = double(pow2(pSrcPoints[0].x) + pow2(pSrcPoints[1].x) + pow2(pSrcPoints[2].x)) / 3.0;
double dbYsYs = double(pow2(pSrcPoints[0].y) + pow2(pSrcPoints[1].y) + pow2(pSrcPoints[2].y)) / 3.0;
double dbXtXs = double(pTemplPoints[0].x * pSrcPoints[0].x +
pTemplPoints[1].x * pSrcPoints[1].x +
pTemplPoints[2].x * pSrcPoints[2].x) / 3.0;
double dbYtYs = double(pTemplPoints[0].y * pSrcPoints[0].y +
pTemplPoints[1].y * pSrcPoints[1].y +
pTemplPoints[2].y * pSrcPoints[2].y) / 3.0;
double dbXtYs = double(pTemplPoints[0].x * pSrcPoints[0].y +
pTemplPoints[1].x * pSrcPoints[1].y +
pTemplPoints[2].x * pSrcPoints[2].y) / 3.0;
double dbYtXs = double(pTemplPoints[0].y * pSrcPoints[0].x +
pTemplPoints[1].y * pSrcPoints[1].x +
pTemplPoints[2].y * pSrcPoints[2].x ) / 3.0;
dbXtXt -= dbXt * dbXt;
dbYtYt -= dbYt * dbYt;
dbXsXs -= dbXs * dbXs;
dbYsYs -= dbYs * dbYs;
dbXtXs -= dbXt * dbXs;
dbYtYs -= dbYt * dbYs;
dbXtYs -= dbXt * dbYs;
dbYtXs -= dbYt * dbXs;
double del = dbXsXs + dbYsYs;
if( del != 0 )
dbLMS = dbXtXt + dbYtYt - ((double)pow(dbXtXs + dbYtYs,2) + (double)pow(dbXtYs - dbYtXs,2)) / del;
return dbLMS;
}

View File

@@ -0,0 +1,84 @@
/*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"
CV_IMPL void
cvDeInterlace( const CvArr* framearr, CvArr* fieldEven, CvArr* fieldOdd )
{
CV_FUNCNAME("cvDeInterlace");
__BEGIN__;
CvMat frame_stub, *frame = (CvMat*)framearr;
CvMat even_stub, *even = (CvMat*)fieldEven;
CvMat odd_stub, *odd = (CvMat*)fieldOdd;
CvSize size;
int y;
CV_CALL( frame = cvGetMat( frame, &frame_stub ));
CV_CALL( even = cvGetMat( even, &even_stub ));
CV_CALL( odd = cvGetMat( odd, &odd_stub ));
if( !CV_ARE_TYPES_EQ( frame, even ) || !CV_ARE_TYPES_EQ( frame, odd ))
CV_ERROR( CV_StsUnmatchedFormats, "All the input images must have the same type" );
if( frame->cols != even->cols || frame->cols != odd->cols ||
frame->rows != even->rows*2 || odd->rows != even->rows )
CV_ERROR( CV_StsUnmatchedSizes, "Uncorrelated sizes of the input image and output fields" );
size = cvGetMatSize( even );
size.width *= CV_ELEM_SIZE( even->type );
for( y = 0; y < size.height; y++ )
{
memcpy( even->data.ptr + even->step*y,
frame->data.ptr + frame->step*y*2, size.width );
memcpy( odd->data.ptr + even->step*y,
frame->data.ptr + frame->step*(y*2+1), size.width );
}
__END__;
}
/* End of file. */