⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iflocation.cpp

📁 A tutorial and open source code for finding edges and corners based on the filters used in primary v
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// IFLocation.cpp: ImageFeatures class CLocation

/*
** Copyright (C) 1994, 2003 Tyler C. Folsom
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation.  This software is provided "as is" without express or
** implied warranty.
*/
#include "stdafx.h"
#include "IFLocation.h"
#include "quad_dis.h"

#include "profile.h"

#define FL4TH  ((float) 0.25)
#define FLHALF ((float) 0.5)
#define FL0    ((float) 0)
#define FL1    ((float) 1)
#define FL2    ((float) 2)
#define FL3    ((float) 3)
#define FL4    ((float) 4)
#define FL5    ((float) 5)
#define FL6    ((float) 6)

/* Solve for angles within 0.1 degree */
#define ANGLE_CONVEGENCE ((float) 0.00174)

#define FACTOR ((float)1.6)

#define EVEN_ORDER 2
#define ODD_ORDER  3
#define G2_ORN (EVEN_ORDER+1)
#define H2_ORN (4)
#define G1_ORN 2
#define H1_ORN 3
#define WAY_SMALL  ((float) -1.0e20)


static float deriv_g2h2( float *gl, float theta);
static float g1h1( float *gl, float theta, float *d1, float *d2);

/*------------------------------------------------------------------------*/
// constructor specifying (x,y) sampling location and
// smaller filter diameter.  Numbers are in pixels.
CLocation::CLocation( int x, int y, int diam )
{
    Initialize( x, y, diam );
}
/*------------------------------------------------------------------------*/
// Initialization specifying (x,y) sampling location and
// smaller filter diameter.  Numbers are in pixels.
void CLocation::Initialize( int x, int y, int diam )
{
    m_x_rf = x;
    m_y_rf = y;
    if (diam > 0)
    {
        m_diam = diam;
        m_usingOdd = false; 
    }
    else
    {
        m_diam = -diam;
        m_usingOdd = true; 
    }
    if ((m_diam & 1) == 0)
        m_big_diam = 2 * m_diam;
    else  /* keep odd filters centered at same point */
        m_big_diam = 2 * m_diam + 1;
    m_usingSmall = true;
}
//----------------------------------------------------------------------------------------
// copy constructor 
CLocation::CLocation(const CLocation &right)
{
    Copy( right );
}
//----------------------------------------------------------------------------------------
//  copy method
void CLocation::Copy(const CLocation &right)
{
    m_x_rf = right.m_x_rf;
    m_y_rf = right.m_y_rf;
    m_usingSmall = right.m_usingSmall;
    m_usingOdd = right.m_usingOdd;
    m_diam = right.m_diam;
    m_big_diam = right.m_big_diam;

    int size = right.corrEven.GetSize();
    corrEven.SetSize(size);
    for (int i = 0; i < size; i++)
    {
        corrEven.SetAt( i, right.corrEven[i]);
    }

    size = right.corrOdd.GetSize();
    corrOdd.SetSize(size);
    for (i = 0; i < size; i++)
    {
        corrOdd.SetAt( i, right.corrOdd[i]);
    }

    size = right.corrBigEven.GetSize();
    corrBigEven.SetSize(size);
    for (i = 0; i < size; i++)
    {
        corrBigEven.SetAt( i, right.corrBigEven[i]);
    }

    size = right.corrBigOdd.GetSize();
    corrBigOdd.SetSize(size);
    for (i = 0; i < size; i++)
    {
        corrBigOdd.SetAt( i, right.corrBigOdd[i]);
    }

}
/*------------------------------------------------------------------------*/
const CLocation &CLocation::operator=( const CLocation &right )
{
    if (&right != this)
    {
        Copy( right );
    }
    return *this;
}
/*------------------------------------------------------------------------*/
// store correlation "result" in slot n of even/odd big/small filter
void CLocation::SetResult( int n, float result)
{
    if (m_usingSmall)
    {
        if (m_usingOdd)
        {
            corrOdd.SetAtGrow( n, result);
        }
        else // small even
        {
            corrEven.SetAtGrow( n, result);
        }
    }
    else  // big filters
    {
        if (m_usingOdd)
        {
            corrBigOdd.SetAtGrow( n, result);
        }
        else // big even
        {
            corrBigEven.SetAtGrow( n, result);
        }
    }
}
/*------------------------------------------------------------------------*/
// return correlation from slot n of even/odd big/small filter
float CLocation::GetResult( int n)
{
    if (m_usingSmall)
    {
        if (m_usingOdd)
        {
            return (corrOdd[n]);
        }
        else // small even
        {
            return (corrEven[n]);
        }
    }
    else  // big filters
    {
        if (m_usingOdd)
        {
            return (corrBigOdd[n]);
        }
        else // big even
        {
            return (corrBigEven[n]);
        }
    }

}
/*------------------------------------------------------------------------*/
// returns a rectangle defining the subimage of the location
RECT CLocation::GetRect()
{
    RECT bounds;
    int low_half;
    int up_half;
    if (m_usingSmall)
    {
        low_half = m_diam / 2;
        up_half = (m_diam+1) / 2;
    }
    else  // big filters
    {
        low_half = m_big_diam / 2;
        up_half = (m_big_diam+1) / 2;
    }
    bounds.left   = m_x_rf - low_half;
    bounds.top    = m_y_rf - low_half;
    bounds.right  = m_x_rf + up_half;
    bounds.bottom = m_y_rf + up_half;
    return bounds;
}

/*------------------------------------------------------------------------*/
// returns an upper bound on the strength
float CLocation::GetStrengthBound()  
{
    float bound = 0;
    for (int i = 0; i < corrOdd.GetSize(); i++)
        bound += FL_ABS(corrOdd[i]);
    for (i = 0; i < corrEven.GetSize(); i++)
        bound += FL_ABS(corrEven[i]);
    return( bound );
}
/*------------------------------------------------------------------------*/
// Steer a filter type to the indicated angle (radians)
float CLocation::Steer( float angle )
{
	PROFILE("Steer");

    float steered = 0;
    if (m_usingSmall)
    {
        if (m_usingOdd)
        {   
            steered = (ODD_ANGLES == 4)? 
                steer_45( corrOdd, angle ): // 4 orientations
                steer_90( corrOdd, angle ); // 2 orientations
        }
        else // small even: 3 orientations
        {
            steered = steer_60( corrEven, angle );
        }
    }
    else  // big filters
    {
        if (m_usingOdd)
        {
            steered = (ODD_ANGLES == 4)? 
                steer_45( corrBigOdd, angle ): // 4 orientations
                steer_90( corrBigOdd, angle ); // 2 orientations
        }
        else // big even: 3 orientations
        {
            steered = steer_60( corrBigEven, angle );
        }
    }
    return steered;
}
/*------------------------------------------------------------------------*/
/* 
    steer_60: Given input filters sampled at 60 degrees, interpolate
    to the filter response at angle theta.

    input:  sampled - response of filters at 0, 60, 120 degrees.
            theta   - angle for desired response in radians.
    returned value: the interpolated filter response at theta.
*/
float CLocation::steer_60( 
    CArray<float, float>& sampled,
    float theta)
{
    float angle;
    float steered;
    int i_angle;

    angle = (float) (PI_1 / G2_ORN);
    steered = (float) 0.0;
    for (i_angle = 0; i_angle < G2_ORN; i_angle++)
        steered += sampled[i_angle] * ((float) 1.0 + (float) 2.0 *
         (float) cos( (double) (2.0 * theta - PI_2 * (float)i_angle / 
         (float) G2_ORN)));
    steered /= G2_ORN;
    return (steered);
}
/*------------------------------------------------------------------------*/
/* 
    steer_45: Given input filters sampled at 45 degrees, interpolate
    to the filter response at angle theta.

    input:  sampled - response of filters at 0, 45, 90, 135 degrees.
            theta   - angle for desired response in radians.
    returned value: the interpolated filter response at theta.
*/
float CLocation::steer_45( 
    CArray<float, float>& sampled,
    float theta)
{
    int angle;
    float steered;

    steered = (float) 0.0;
    for (angle = 0; angle < H2_ORN; angle++)
        steered += sampled[angle] * (float) ( 
         cos( (double) theta - PI_1 * (float)angle / (float) H2_ORN) +
         cos( theta * 3.0 - PI_3 * (float) angle / (float) H2_ORN));
    steered /= (float) 2.0;
    return (steered);
}
/*------------------------------------------------------------------------*/
/* 
    steer_90: Given input filters sampled at 90 degrees, interpolate
    to the filter response at angle theta.

    input:  sampled - response of filters at 0, 90 degrees.
            theta   - angle for desired response in radians.
    returned value: the interpolated filter response at theta.
*/
float CLocation::steer_90( 
    CArray<float, float>& sampled,
    float theta)
{
    return ( (float) (sampled[0] * cos( (double) theta)
                    + sampled[1] * sin( (double) theta)) );
}
/*------------------------------------------------------------------------*/
// Finds the angle (radians) of the feature based on filter correlations
/* 
    GetAngle: Given input filters sampled at 60 and 90 degrees, find the angle
    of the dominant response.

    input:  corrEven - response of even filters at 0, 60, 120 degrees.
            corrOdd - response of odd filters at 0 and 90 degrees.
    output: dom_resp - squared response of the filter at the dominant angle.
            *steeredEven - interpolated even response at the dominant angle.
            *steeredOdd - interpolated odd response at the dominant angle.
    returned value: angle of dominant response in radians.

    There are two methods here.  The older, obsolete, method is based on using
     corrOdd - response of odd filters at 0, 45, 90, 135 degrees.
	The solve() and deriv_g2h2() routines find the angle where the derivative is zero.

    The newer, more efficient, method uses solve_max() and g1h1() to find the 
	angle that gives maximum response.  For documentation, see the header for
	g1h1()  and  Folsom & Pinter, "Primitive Features by Steering, Quadrature
	and Scale", IEEE Trans PAMI, Nov 1998, pp. 1161-1173.

*/
float CLocation::GetAngle( 
    float *dom_resp,
    float *steeredEven,
    float *steeredOdd,
	bool  noSteering) // no steering if true

{
	PROFILE("CLocation::GetAngle");

    float gl[7];  /* gamma and lamda coefficients */
    float coef[8];  /* combinations of gamma and lambda for trig terms*/
    float angles[4];  /* 4 solutions */
    float dom2;
    float dom1;
    float theta1, theta;
    float theta_rad;
    float max_mag, mag_sq;

	if (m_x_rf == 77 && m_y_rf == 87)
	{
		max_mag = 10;  // break here to debug
	}
    max_mag = WAY_SMALL;
    /* Gamma1, gamma2, gamma3 */
    gl[0] = (corrEven[0] + corrEven[1] + corrEven[2]) / FL3;
    gl[1] = (FL2 * corrEven[0] - corrEven[1] - corrEven[2]) / FL3;
    gl[2] = (corrEven[1] - corrEven[2]) / ROOT_3;
    if (ODD_ANGLES == 4)
    {
        /* Lambda1, .. lambda3 */
        gl[3] = (corrOdd[0] + (corrOdd[1] - corrOdd[3]) / ROOT_2) / FL2;
        gl[4] = (corrOdd[2] + (corrOdd[1] + corrOdd[3]) / ROOT_2) / FL2;
        gl[5] = (corrOdd[0] - (corrOdd[1] - corrOdd[3]) / ROOT_2) / FL2;
        gl[6] = (-corrOdd[2] + (corrOdd[1] + corrOdd[3]) / ROOT_2) / FL2;
        coef[0] = FL2 * (FL2*gl[0]*gl[2] + gl[3]*gl[4] - gl[4]*gl[5] + gl[3]*gl[6]);
        coef[1] = -(FL4*gl[0]*gl[1] + gl[3]*gl[3] - gl[4]*gl[4] + FL2*gl[3]*gl[5]
         + FL2*gl[4]*gl[6]);
        coef[2] = FL4 * (gl[1]*gl[2] + gl[4]*gl[5] + gl[3]*gl[6]);
        coef[3] = FL2 * (-gl[1]*gl[1] + gl[2]*gl[2] - FL2*gl[3]*gl[5]
         + FL2*gl[4]*gl[6]);
        coef[4] = FL6 * gl[5]*gl[6];
        coef[5] = FL3*(-gl[5]*gl[5] + gl[6]*gl[6]);

        /* try arbitrary initial guess for theta */
        for (theta = FL0; theta < PI_1;)
        {
            theta1 = theta;
		    if (!noSteering)
		    {	// Find the strongest angle near this guess
			    solve (coef, &theta1, deriv_g2h2);
		    }
            dom1 = steer_45 (corrOdd, theta1);
            dom2 = steer_60 (corrEven, theta1);
            mag_sq = dom1 * dom1 + dom2 * dom2;
            if (mag_sq >= max_mag)
            {
                max_mag = mag_sq;
                theta_rad = theta1;
                *steeredEven = dom2;
                *steeredOdd = dom1;
            }
		    if (noSteering)
		    {	// skip if not looking for the angle.
			    break;
		    }
            /* start next guess about 1 degree beyond previous root. */
            theta = theta1 + (float) 0.02;
        }
        *dom_resp = max_mag;
        return (theta_rad);
    }
    else
    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -