This program supports the Image processing micon car production kit (M-S348).

Dependencies:   GR-PEACH_video mbed

image_process.cpp

Committer:
TetsuyaKonno
Date:
2018-10-30
Revision:
0:00b6f7454ada

File content as of revision 0:00b6f7454ada:

//------------------------------------------------------------------//
//Supported MCU:   RZ/A1H
//File Contents:   Image Processing API ( Source file )
//Version number:  Ver.1.00
//Date:            2018.10.30
//Copyright:       Renesas Electronics Corporation
//                 Hitachi Document Solutions Co., Ltd.
//------------------------------------------------------------------//

//------------------------------------------------------------------//
//Include
//------------------------------------------------------------------//
#include <math.h>
#include "mbed.h"
#include "image_process.h"

/*******************************/
/* Function Map                */
/********************************
* ImageCopy
* Extraction_Brightness
* ImageReduction
* Binarization
* Image_part_Extraction
* Standard_Deviation
* Covariance
* Judgement_ImageMatching
* PatternMatching_process
********************************/

//******************************************************************//
// Image process functions
//*******************************************************************/
//------------------------------------------------------------------//
// ImageCopy function
//------------------------------------------------------------------//
void ImageCopy( unsigned char *BuffAddrIn, int HW, int VW, unsigned char *BuffAddrOut, int Frame )
{
    static int  counter = 0;
    static int  X, Y;
    int         HW_T;//HW Twice

    HW_T  = HW + HW;

    switch( counter++ ) {
    case 0:
        // Top or Bottom field
        for( Y = Frame; Y < ( VW / 2 ); Y+=2 ){
            for( X = 0; X < HW_T; X++ ){
                BuffAddrOut[ ( Y * HW_T ) + X ] = BuffAddrIn[ ( Y * HW_T ) + X ];
            }
        }
        break;
    case 1:
        // Top or Bottom field
        for(          ; Y < VW; Y+=2 ){
            for( X = 0; X < HW_T; X++ ){
                BuffAddrOut[ ( Y * HW_T ) + X ] = BuffAddrIn[ ( Y * HW_T ) + X ];
            }
        }
        //Frame Change
        if( Frame == 0 ) Frame = 1;
        else             Frame = 0;
        for( Y = Frame; Y < VW; Y+=2 ){
            for( X = 0; X < HW_T; X+=2 ){
                BuffAddrOut[ ( Y * HW_T ) + ( X + 0 ) ] = 0;
                BuffAddrOut[ ( Y * HW_T ) + ( X + 1 ) ] = 128;
            }
        }
        counter = 0;
        break;
    default:
        break;
    }
}

//------------------------------------------------------------------//
// Extraction Brightness function
//------------------------------------------------------------------//
void Extraction_Brightness( unsigned char *BuffAddrIn, int HW, int VW, unsigned char *BuffAddrOut, int Frame )
{
    static int  conter = 0;

    int X, Y;
    int Px;
    int HW_T;//HW Twice

    HW_T  = HW + HW;

    switch( conter++ ) {
    case 0:
        //Pixel Interpolation ( Top or Bottom )
        for( Y = Frame; Y < ( VW / 2 ); Y+=2 ){
            for( X = 0, Px = 0; X < HW_T; X+=2, Px++  ){
                BuffAddrOut[ ( Y * HW ) + Px ] = BuffAddrIn[ ( Y * HW_T ) + X ];
            }
        }
        //Frame Change
        if( Frame == 0 ) Frame = 1;
        else             Frame = 0;
        //Bilinear Interpolation Method
        for( Y = Frame; Y < ( VW / 2 ); Y+=2 ){
            for( X = 0, Px = 0; X < HW_T; X+=2, Px++  ){
                if( Y <= 0 ) {
                    BuffAddrOut[ ( Y * HW ) + Px ] = BuffAddrOut[ ( (Y+1) * HW ) + Px ];
                } else if( ( ( VW / 2 ) - 1 ) > Y && Y > 0 ) {
                    BuffAddrOut[ ( Y * HW ) + Px ] = ( BuffAddrOut[ ( (Y-1) * HW ) + Px ] * (double)0.5 ) + ( BuffAddrOut[ ( (Y+1) * HW ) + Px ] * (double)0.5 );
                } else if( Y >= ( ( VW / 2 ) - 1 ) ) {
                    BuffAddrOut[ ( Y * HW ) + Px ] = BuffAddrOut[ ( (Y-1) * HW ) + Px ];
                }
            }
        }
        break;
    case 1:
        //Pixel Interpolation ( Top or Bottom )
        for( Y = ( VW / 2 ) + Frame; Y < VW; Y+=2 ){
            for( X = 0, Px = 0; X < HW_T; X+=2, Px++  ){
                BuffAddrOut[ ( Y * HW ) + Px ] = BuffAddrIn[ ( Y * HW_T ) + X ];
            }
        }
        //Frame Change
        if( Frame == 0 ) Frame = 1;
        else             Frame = 0;
        //Bilinear Interpolation Method
        for( Y = ( VW / 2 ) + Frame; Y < VW; Y+=2 ){
            for( X = 0, Px = 0; X < HW_T; X+=2, Px++  ){
                if( Y <= 0 ) {
                    BuffAddrOut[ ( Y * HW ) + Px ] = BuffAddrOut[ ( (Y+1) * HW ) + Px ];
                } else if( ( VW - 1 ) > Y && Y > 0 ) {
                    BuffAddrOut[ ( Y * HW ) + Px ] = ( BuffAddrOut[ ( (Y-1) * HW ) + Px ] * (double)0.5 ) + ( BuffAddrOut[ ( (Y+1) * HW ) + Px ] * (double)0.5 );
                } else if( Y >= ( VW - 1 ) ) {
                    BuffAddrOut[ ( Y * HW ) + Px ] = BuffAddrOut[ ( (Y-1) * HW ) + Px ];
                }
            }
        }
        conter = 0;
        break;
    default:
        break;
    }
}

//------------------------------------------------------------------//
// Image Reduction function
// Parcent : 0.0 - 1.0
//------------------------------------------------------------------//
void ImageReduction( unsigned char *BuffAddrIn, int HW, int VW, unsigned char *BuffAddrOut, double Percent )
{
    static int      conter = 0;
    static int      Y;

    int             X;
    int             HW_N;
    long            Nx, Ny;
    long            NxBuff, NyBuff;
    unsigned int    BuffAddrData;
    double long     Sx, Sy;

    NxBuff  = -1;
    Sx = Sy = Percent;
    HW_N    = HW * Percent;

    //Under 100%
    if( Percent <= 1 ) {
        switch( conter++ ) {
        case 0:
            for( Y = 0; Y < ( VW / 2 ); Y++ ){
                //Affine Transformation Y-axis
                Ny = ( Sy * Y );
                for( X = 0; X < HW; X++ ){
                    //Affine Transformation X-axis
                    Nx = ( Sx * X );
                    if( NxBuff == Nx ) {
                        BuffAddrData  = BuffAddrOut[ ( Ny * HW_N ) + Nx ];
                        BuffAddrData += BuffAddrIn[ ( Y * HW ) + X ];
                        BuffAddrData /= 2;
                        BuffAddrOut[ ( Ny * HW_N ) + Nx ] = BuffAddrData;
                    } else {
                        NxBuff = Nx;
                        BuffAddrOut[ ( Ny * HW_N ) + Nx ] = BuffAddrIn[ ( Y * HW ) + X ];
                    }
                }
                if( NyBuff == Ny ) {
                    for( X = 0; X < HW_N; X++ ){
                        BuffAddrData  = BuffAddrOut[ (  Ny      * HW_N ) + X ];//Now line
                        BuffAddrData += BuffAddrOut[ ( (Ny - 1) * HW_N ) + X ];//Before now line
                        BuffAddrData /= 2;
                        BuffAddrOut[ ( Ny * HW_N ) + X ] = BuffAddrData;
                    }
                } else {
                    NyBuff = Ny;
                }
            }
            break;
        case 1:
            for(      ; Y < VW; Y++ ){
                //Affine Transformation Y-axis
                Ny = ( Sy * Y );
                for( X = 0; X < HW; X++ ){
                    //Affine Transformation X-axis
                    Nx = ( Sx * X );
                    if( NxBuff == Nx ) {
                        BuffAddrData  = BuffAddrOut[ ( Ny * HW_N ) + Nx ];
                        BuffAddrData += BuffAddrIn[ ( Y * HW ) + X ];
                        BuffAddrData /= 2;
                        BuffAddrOut[ ( Ny * HW_N ) + Nx ] = BuffAddrData;
                    } else {
                        NxBuff = Nx;
                        BuffAddrOut[ ( Ny * HW_N ) + Nx ] = BuffAddrIn[ ( Y * HW ) + X ];
                    }
                }
                if( NyBuff == Ny ) {
                    for( X = 0; X < HW_N; X++ ){
                        BuffAddrData  = BuffAddrOut[ (  Ny      * HW_N ) + X ];//Now line
                        BuffAddrData += BuffAddrOut[ ( (Ny - 1) * HW_N ) + X ];//Before now line
                        BuffAddrData /= 2;
                        BuffAddrOut[ ( Ny * HW_N ) + X ] = BuffAddrData;
                    }
                } else {
                    NyBuff = Ny;
                }
            }
            conter = 0;
            break;
        default:
            break;
        }
    }
}

//------------------------------------------------------------------//
// Binarization process Function
//------------------------------------------------------------------//
void Binarization( unsigned char *BuffAddrIn, int HW, int VW, unsigned char *BuffAddrOut, int threshold )
{
    int     i;
    int     items;

    items = HW * VW;

    for( i = 0; i < items; i++ ) {
        if( BuffAddrIn[i] >= threshold ) BuffAddrOut[i] = 1;
        else                             BuffAddrOut[i] = 0;
    }
}

//******************************************************************//
// Mark detect functions
//*******************************************************************/
//------------------------------------------------------------------//
// Extract_Image
//------------------------------------------------------------------//
void Image_part_Extraction( unsigned char *BuffAddrIn, int HW, int VW,
                            int CutPointX, int CutPointY, unsigned char *BuffAddrOut, int Xsize, int Ysize )
{
    int     X, Y;
    for( Y = 0; Y < Ysize; Y++ ) {
        for( X = 0; X < Xsize; X++ ) {
            BuffAddrOut[ X + ( Y * Xsize ) ] = BuffAddrIn[ ( ( Y + CutPointY ) * HW ) + ( X + CutPointX ) ];
       }
    }
}

//------------------------------------------------------------------//
// Standard deviation
//------------------------------------------------------------------//
double Standard_Deviation( unsigned char *data, double *Devi, int Xsize, int Ysize )
{
    int         i;
    int         items;
    double      iRet_A, iRet_C, iRet_D;

    items = Xsize * Ysize;

    /* A 合計値 平均化 */
    iRet_A = 0;
    for( i = 0; i < items; i++ ) {
        iRet_A += data[i];
    }
    iRet_A /= items;

    /* B 偏差値 */
    for( i = 0; i < items; i++ ) {
        Devi[i] = data[i] - iRet_A;
    }

    /* C 分散 */
    iRet_C = 0;
    for( i = 0; i < items; i++ ) {
        iRet_C += ( Devi[i] * Devi[i] );
    }
    iRet_C /= items;

    /* D 標準偏差 */
    iRet_D = sqrt( iRet_C );

    return iRet_D;
}

//------------------------------------------------------------------//
// Covariance
//------------------------------------------------------------------//
double Covariance( double *Devi_A, double *Devi_B, int Xsize, int Ysize )
{
    int     i;
    int         items;
    double  iRet, iRet_buff;

    items = Xsize * Ysize;

    iRet = 0;
    for( i = 0; i < items; i++ ) {
        iRet_buff = Devi_A[i] * Devi_B[i];
        iRet     += iRet_buff;
    }
    iRet /= items;

    return iRet;
}

//------------------------------------------------------------------//
// Judgement_ImageMatching
//------------------------------------------------------------------//
int Judgement_ImageMatching( double Covari, double SDevi_A, double SDevi_B )
{
    int     iRet;

    iRet  = ( Covari * 100 ) / ( SDevi_A * SDevi_B );

    return iRet;
}

//------------------------------------------------------------------//
// Pattern Matching process
//------------------------------------------------------------------//
void PatternMatching_process( unsigned char *BuffAddrIn, int HW, int VW,
                              ImagePartPattern *Temp, int Xs, int Xe, int Ys, int Ye )
{
    ImagePartPattern    NowImage;
    volatile int        x, y;
    volatile int        retJudge;
    volatile double     retCovari;

    Temp->p = 0;
    for( y = Ys; y <= Ye; y++ ) {
        for( x = Xs; x <= Xe; x++ ) {
            Image_part_Extraction( BuffAddrIn, HW, VW, x, y, NowImage.binary, Temp->w, Temp->h );
            NowImage.sdevi = Standard_Deviation( NowImage.binary, NowImage.devi, Temp->w, Temp->h);
            retCovari      = Covariance( Temp->devi, NowImage.devi, Temp->w, Temp->h );
            retJudge       = 0;
            retJudge       = Judgement_ImageMatching( retCovari, Temp->sdevi, NowImage.sdevi );
            if( 100 >= retJudge && retJudge > Temp->p ) {
                Temp->x = x;
                Temp->y = y;
                Temp->p = retJudge;
            }
        }
    }
}

//------------------------------------------------------------------//
// End of file
//------------------------------------------------------------------//