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

📄 processfeatures.cpp

📁 A tutorial and open source code for finding edges and corners based on the filters used in primary v
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*
** 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.
*/
/*

ProcessFeatures.cpp


The user opens an image, which is displayed in its own window.  
He / She then selects Process / Find Features.  This establishes
a linkage between the input image (the opened image most 
recently active), the grid file (default name is grid.txt), 
the text output file (same name as the image file with an extension
of ".txt") and the graphical output file (same name as the image 
file, but with a "$" inserted before the extension)
If the grid file has not previously been read, it is opened and read.

For each filter location
{
	Create new filters of this size if needed.
	Acquire a subimage for the bigger filter
	Apply filters to the big subimage.
	Acquire a subimage for the smaller filter
	Apply filters to the small subimage.
	Use the filter results to produce feature characteristics
	Add the feature to the text output file.
}
Save and display the text output file.
Generate information for graphics display.
Display the graphics output.
*/

#include "stdafx.h"
#include "ProcessFeatures.h"

#include "quad_dis.h"  // for FL_ABS()
#include "typeinfo.h"

#include "profile.h"

// Initialize static data member
CMap<int, int&, CFilter, CFilter&> CProcessFeatures::m_filters;

/*------------------------------------------------------------------------*/
// This does the main work.
bool CProcessFeatures::Process( grid_type grid)
{
	PROFILE("CProcessFeatures::Process");

#ifdef TRACE_ME
	ofstream traceFile( "Trace.txt", ios::out );
	traceFile << "Starting Process" << endl;
	traceFile.close();
#endif // TRACE_ME
    bool success = false;
    // Read a file and construct CLocations at which to filter
    switch (grid)
    {
    case eTest1D:
        success = Make1DGrid();
        break;
    case eTest2D:
        success = Make2DGrid();
        break;
    default:
    case eMakeGrid:
        success = MakeGrid();
        break;
    case eReadGrid:
        success = ReadGrid();
    }
    if (!success)
        return false;   // can't get the sampling locations.

    m_features.RemoveAll();  // get rid of any previous features.
    // iterate on m_locs  
    for ( int n = 0; n < m_locs.GetSize(); n++) 
    {
        CLocation location = m_locs[n];
        if (Filter( location )) // filter at this location
        {
            Interpret( location ); // find feature at this location
        }
    }

	FindNeighbors();

    // iterate on m_features  
    for ( n = 0; n < m_features.GetSize(); n++) 
    {   // facilitate or inhibit based on neighbors.
        m_features[n].LateralAntagonism();
    }
    for ( n = 0; n < m_features.GetSize(); n++) 
    {   // remove features below threshold.
		if (m_features[n].GetStrength() 
			+ m_lateralFactor * m_features[n].GetAntagonism()
			< m_threshold)
			m_features.RemoveAt(n);
	}

#ifdef TRACE_ME
	traceFile << "Completed Process" << endl;
	traceFile.close();
#endif // TRACE_ME

    return true;
}
/*------------------------------------------------------------------------*/
// If using a templated version of the image, would declare as:
// template<class TPixel>CProcessFeatures<TPixel>::CProcessFeatures( )
CProcessFeatures::CProcessFeatures( )
{
    m_gridFileName = "grid.txt";
    m_threshold = (float) 0.20;
	m_fixedDirection = false;
	// This is the minimum overlap that will cover the whole image
	m_overlap = (float) (PI_2 / (3 * ROOT_3)); // 1.209
	m_filterDiam = 8;
	m_displayTestImages = false;
	m_testImageContrast = 20;
	m_testImageNoise = 20;
    m_viewEdgesOnly = false;
    m_viewGrid = false;
	m_subSampleDiam = DEFAULT_SUBSAMPLE_DIAM;
	m_lateralFactor = DEFAULT_LATERAL;
    SetAnswer();
}
//----------------------------------------------------------------------------------------
// constructor for creating the answer for test images 
void CProcessFeatures::SetAnswer
(   feature_type type,
    float x,    // center point of feature
    float y,    // center point of feature
    float degrees,
    float strength,
    float width
)
{
    // Originally a right pointing horizontal line was 0 degrees.
    // It has been redefined so that 0 degrees points down.  7/1/03
    // The 0 degree kernel had been horizontal; it is now vertical.  5/20/03.
    // Test images use the old convention.
    m_answer.m_degrees = degrees + 90;
    while (m_answer.m_degrees >= 360)
        m_answer.m_degrees -= 360;
    m_answer.m_corrEven = 0;
    m_answer.m_corrOdd = 0;
    m_answer.m_corrBigEven = 0;
    m_answer.m_corrBigOdd = 0;
    m_answer.m_strength = strength;
    m_answer.m_x = x;
    m_answer.m_y = y;
    m_answer.m_pos = 0;  // depends on where filter is
    m_answer.m_type = type;
    m_answer.m_width = width;
	m_answer.m_cos_th = cos(m_answer.m_degrees * PI / 180.0);
	m_answer.m_sin_th = sin(m_answer.m_degrees * PI / 180.0);
}
/*------------------------------------------------------------------------*/
// Construct CLocations at which to filter an image.
// Return "true" if succesful.
bool CProcessFeatures::MakeGrid()
{
    if (m_filterDiam < 2)
        return false;  // filter is too small
    if (m_bounds.right < 2 * m_filterDiam ||
        m_bounds.bottom < 2 * m_filterDiam)
        return false;   // filter is too big
    int row = m_filterDiam - 1; // big filter just hits row 0
    int col = m_filterDiam - 1; // big filter just hits column 0
    double centerToCenter = m_filterDiam * 
        sqrt(PI_HALF / (ROOT_3 * m_overlap));
    int row_space = (int) centerToCenter;  
    if (row_space < 2)
        row_space = 2;
    int col_space = (int) (ROOT_3 *  centerToCenter);
    if (col_space < 2)
        col_space = 2;

    m_locs.RemoveAll();  // get rid of any previous locations.
    for (int format = 0; format < 2; format++) // overlapped grids
    {
        for (int c = col; c < m_bounds.right; c += col_space)
        {
            for (int r = row; r < m_bounds.bottom; r += row_space)
            {
                CLocation newLoc( c, r, m_filterDiam ); // create location
                newLoc.SetSmall( false ); // look at bigger region
                RECT big = newLoc.GetRect();
                if (big.left   >= m_bounds.left &&
                    big.top    >= m_bounds.top  &&
                    big.right  <= m_bounds.right &&
                    big.bottom <= m_bounds.bottom)
                {   // add this location to the list.
                    m_locs.Add( newLoc );
                }
            }
        }	// loop on columns
        row += row_space/2;
		col += col_space/2;
    }	// loop on overlapped grids
    return true;
}
/*------------------------------------------------------------------------*/
// Construct CLocations at which to filter a 1D test image.
// Return "true" if succesful.
bool CProcessFeatures::Make1DGrid()
{
    if (m_filterDiam < 2)
        return false;  // filter is too small
    // assumes m_bounds.left = m_bounds.top = 0
    if (m_bounds.right < 2 * m_filterDiam ||
        m_bounds.bottom < 2 * m_filterDiam)
        return false;   // filter is too big
    int row = m_bounds.bottom/2; // only the center row
    int col = (m_bounds.right- m_filterDiam)/2 - 1; // small filter just hits center
    int col_last = (m_bounds.right + m_filterDiam)/2; // small filter just hits center
    int col_space = 1;

    m_locs.RemoveAll();  // get rid of any previous locations.
    for (int c = col; c < col_last; c += col_space)
    {
        CLocation newLoc( c, row, m_filterDiam ); // create location
        newLoc.SetSmall( false ); // look at bigger region
        RECT big = newLoc.GetRect();
        if (big.left   >= m_bounds.left &&
            big.top    >= m_bounds.top  &&
            big.right  <= m_bounds.right &&
            big.bottom <= m_bounds.bottom)
        {   // add this location to the list.
            m_locs.Add( newLoc );
        }
    }	// loop on columns
    return true;
}
/*------------------------------------------------------------------------*/
// Construct CLocations at which to filter a 2D test image.
// Return "true" if succesful.
bool CProcessFeatures::Make2DGrid()
{
    if (m_filterDiam < 2)
        return false;  // filter is too small
    if (m_bounds.right < 2 * m_filterDiam ||
        m_bounds.bottom < 2 * m_filterDiam)
        return false;   // filter is too big
    int row = (m_bounds.bottom- m_filterDiam)/2 - 1; // small filter just hits center
    int col = (m_bounds.right- m_filterDiam)/2 - 1; // small filter just hits center
    int row_space = 1;
    int col_space = 1;
    float radius_squared = m_filterDiam * m_filterDiam * (float) 0.25;
    float row_center = (m_bounds.bottom - 1 )* (float) 0.5;
    float col_center = (m_bounds.right - 1 )* (float) 0.5;
    int row_last = (int) (row_center + m_filterDiam * (float) 0.5);
    int col_last = (int) (col_center + m_filterDiam * (float) 0.5);

    m_locs.RemoveAll();  // get rid of any previous locations.
    for (int c = col; c < col_last; c += col_space)
    {
        float c_sqr = (c - col_center) * (c - col_center);
        for (int r = row; r < row_last; r += row_space)
        {   
            if ((r - row_center) * (r - row_center) + c_sqr > radius_squared)
                continue;  // filter would not hot the center point
            CLocation newLoc( c, r, m_filterDiam ); // create location
            newLoc.SetSmall( false ); // look at bigger region
            RECT big = newLoc.GetRect();
            if (big.left   >= m_bounds.left &&
                big.top    >= m_bounds.top  &&
                big.right  <= m_bounds.right &&
                big.bottom <= m_bounds.bottom)
            {   // add this location to the list.
                m_locs.Add( newLoc );
            }
        }
    }	// loop on columns
    return true;
}
/*------------------------------------------------------------------------*/
// Read a file and construct CLocations at which to filter
// If m_locs is empty, fill it by reading from m_gridFileName.
// Return "true" if succesful.
bool CProcessFeatures::ReadGrid()
{
	PROFILE("ReadGrid");

    ifstream inGrid( m_gridFileName, ios::in );
//  if (!inGrid)
//		return false; // can't open file

//  If the file read does not work, provide these hardcoded values.
    int gridMethod = 0;
    float threshold;  // ignored; m_threshold is hard-coded.
    int diameter = 32; // 8;
    int row = 35;  // 3 or 7;
    int col = 32;  // 3 or 7;
    int row_space = 27; // 8;
    int col_space = 54; // 8;

    int image_rows = 64; // only used for old style gridMethod 1.
    int image_cols = 64;
    int format = 0;
    bool got_some = false;

    m_locs.RemoveAll();  // get rid of any previous locations.

//  if (inGrid >> gridMethod)
//      return false;  // can't read

    switch (gridMethod)
    {
    case 1: // old style; everything given explicitly
        if (inGrid >>threshold)
            return got_some; // can't read threshold.
        if (inGrid >> diameter)
            return got_some; // can't read.
        if (diameter < 3)
            return got_some;
        if (inGrid >> format >> image_rows >> image_cols) // ignore
            return got_some; // can't read.
        while (inGrid >> row >> col)
        {
            CLocation newLoc( col, row, diameter ); // create location
            newLoc.SetSmall( false ); // look at bigger region
            RECT big = newLoc.GetRect();
            if (big.left   >= m_bounds.left &&
                big.top    >= m_bounds.top  &&
                big.right  <= m_bounds.right &&
                big.bottom <= m_bounds.bottom)
            {   // add this location to the list.
                m_locs.Add( newLoc );
            }
        }
        break;

    case 0: // read failure; use hardcoded values.
        for (format = 0; format < 2; format++) // overlapped grids
        {
            for (int c = col; c < m_bounds.right; c += col_space)
            {
                for (int r = row; r < m_bounds.bottom; r += row_space)
                {
                    CLocation newLoc( c, r, diameter ); // create location
                    newLoc.SetSmall( false ); // look at bigger region
                    RECT big = newLoc.GetRect();
                    if (big.left   >= m_bounds.left &&
                        big.top    >= m_bounds.top  &&
                        big.right  <= m_bounds.right &&
                        big.bottom <= m_bounds.bottom)
                    {   // add this location to the list.
                        m_locs.Add( newLoc );
                    }
                }
            }	// loop on columns
            row += row_space/2;
			col += col_space/2;
        }	// loop on overlapped grids
        got_some = true;
        break;

    case 2: // new style; use repeat block
        if (inGrid >>threshold)
            return got_some; // can't read threshold.
        while (inGrid >> diameter >> row >> col >> row_space >> col_space)
        {
            if (diameter < 3)
                return got_some; // diameter too small
            for (int c = col; c < m_bounds.right; c += col_space)
            {
                for (int r = row; r < m_bounds.bottom; r += row_space)
                {
                    CLocation newLoc( c, r, diameter ); // create location
                    newLoc.SetSmall( false ); // look at bigger region
                    RECT big = newLoc.GetRect();
                    if (big.left   >= m_bounds.left &&
                        big.top    >= m_bounds.top  &&
                        big.right  <= m_bounds.right &&
                        big.bottom <= m_bounds.bottom)
                    {   // add this location to the list.
                        m_locs.Add( newLoc );
                    }
                }
            }
        } // exit loop when no more to read.
        break;

    case 97: // read failure; use hardcoded values.
        row = 5;  // larger grid with 12 pixel filters.

⌨️ 快捷键说明

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