You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
6.6 KiB
187 lines
6.6 KiB
/** @file */
|
|
/* The MIT License
|
|
*
|
|
* Copyright (c) 2008, Naotoshi Seo <sonots(at)sonots.com>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*/
|
|
#ifndef CV_CREATEAFFINEIMAGE_INCLUDED
|
|
#define CV_CREATEAFFINEIMAGE_INCLUDED
|
|
|
|
#include "cv.h"
|
|
#include "cvaux.h"
|
|
#include "cxcore.h"
|
|
#define _USE_MATH_DEFINES
|
|
#include <math.h>
|
|
#include <limits.h>
|
|
|
|
#include "cvinvaffine.h"
|
|
|
|
#define CV_AFFINE_SAME 0
|
|
#define CV_AFFINE_FULL 1
|
|
|
|
//CV_INLINE IplImage*
|
|
//cvCreateAffineMask( const IplImage* src, const CvMat* affine,
|
|
// int flags = CV_AFFINE_SAME, CvPoint* origin = NULL );
|
|
//IplImage*
|
|
//cvCreateAffineImage( const IplImage* src, const CvMat* affine,
|
|
// int flags = CV_AFFINE_SAME, CvPoint* origin = NULL,
|
|
// CvScalar bgcolor = CV_RGB(0,0,0) );
|
|
|
|
/**
|
|
* Affine transform of an image.
|
|
*
|
|
* Memory is allocated. Do not forget cvReleaseImage( &ret );
|
|
*
|
|
* @param src Image
|
|
* @param affine 2 x 3 Affine transform matrix
|
|
* @param flags CV_AFFINE_SAME - Outside image coordinates are cut off.
|
|
* CV_AFFINE_FULL - Fully contain the original image pixel values
|
|
* @param origin The coordinate of origin is returned. The origin is the
|
|
* coordinate in original image respective to the transformed
|
|
* image origin. Useful when CV_AFFINE_FULL is used.
|
|
* @param bgcolor The color used when corresponding coordinate is not
|
|
* available in the original image.
|
|
* @return
|
|
* @see cvWarpAffine
|
|
* this does not support CV_AFFINE_FULL, but supports
|
|
* everal interpolation methods and so on.
|
|
*/
|
|
IplImage*
|
|
cvCreateAffineImage( const IplImage* src, const CvMat* affine,
|
|
int flags = CV_AFFINE_SAME, CvPoint* origin = NULL,
|
|
CvScalar bgcolor = CV_RGB(0,0,0) )
|
|
{
|
|
IplImage* dst;
|
|
int minx = INT_MAX;
|
|
int miny = INT_MAX;
|
|
int maxx = INT_MIN;
|
|
int maxy = INT_MIN;
|
|
int i, x, y, xx, yy, xp, yp;
|
|
int ch, width, height;
|
|
CvPoint pt[4];
|
|
CvMat* invaffine;
|
|
CV_FUNCNAME( "cvAffineImage" );
|
|
__CV_BEGIN__;
|
|
CV_ASSERT( src->depth == IPL_DEPTH_8U );
|
|
CV_ASSERT( affine->rows == 2 && affine->cols == 3 );
|
|
|
|
// cvBoxPoints supports only rotation (no shear deform)
|
|
// original 4 corner
|
|
pt[0].x = 0; pt[0].y = 0;
|
|
pt[1].x = src->width - 1; pt[1].y = 0;
|
|
pt[2].x = 0; pt[2].y = src->height - 1;
|
|
pt[3].x = src->width - 1; pt[3].y = src->height - 1;
|
|
// 4 corner after transformed
|
|
for( i = 0; i < 4; i++ )
|
|
{
|
|
x = cvRound( pt[i].x * cvmGet( affine, 0, 0 ) +
|
|
pt[i].y * cvmGet( affine, 0, 1 ) +
|
|
cvmGet( affine, 0, 2 ) );
|
|
y = cvRound( pt[i].x * cvmGet( affine, 1, 0 ) +
|
|
pt[i].y * cvmGet( affine, 1, 1 ) +
|
|
cvmGet( affine, 1, 2 ) );
|
|
pt[i].x = x; pt[i].y = y;
|
|
}
|
|
// min, max
|
|
for( i = 0; i < 4; i++ )
|
|
{
|
|
minx = MIN( pt[i].x, minx );
|
|
miny = MIN( pt[i].y, miny );
|
|
maxx = MAX( pt[i].x, maxx );
|
|
maxy = MAX( pt[i].y, maxy );
|
|
}
|
|
// target image width and height
|
|
if( flags == CV_AFFINE_FULL )
|
|
{
|
|
width = maxx - minx + 1;
|
|
height = maxy - miny + 1;
|
|
}
|
|
else if( flags == CV_AFFINE_SAME )
|
|
{
|
|
width = src->width;
|
|
height = src->height;
|
|
minx = miny = 0;
|
|
maxx = src->width - 1;
|
|
maxy = src->height - 1;
|
|
}
|
|
//cvPrintMat( affine );
|
|
//printf( "%d %d %d %d\n", minx, miny, maxx, maxy );
|
|
if( origin != NULL )
|
|
{
|
|
origin->x = minx;
|
|
origin->y = miny;
|
|
}
|
|
dst = cvCreateImage( cvSize(width, height), src->depth, src->nChannels );
|
|
cvSet( dst, bgcolor );
|
|
|
|
// inverse affine
|
|
invaffine = cvCreateMat( 2, 3, affine->type );
|
|
cvInvAffine( affine, invaffine );
|
|
|
|
// loop based on image coordinates of transformed image
|
|
for( x = 0; x < width; x++ )
|
|
{
|
|
xx = x + minx;
|
|
for( y = 0; y < height; y++ )
|
|
{
|
|
yy = y + miny;
|
|
xp = cvRound( xx * cvmGet( invaffine, 0, 0 ) +
|
|
yy * cvmGet( invaffine, 0, 1 ) +
|
|
cvmGet( invaffine, 0, 2 ) );
|
|
yp = cvRound( xx * cvmGet( invaffine, 1, 0 ) +
|
|
yy * cvmGet( invaffine, 1, 1 ) +
|
|
cvmGet( invaffine, 1, 2 ) );
|
|
if( xp < 0 || xp >= src->width || yp < 0 || yp >= src->height ) continue;
|
|
for( ch = 0; ch < src->nChannels; ch++ )
|
|
{
|
|
dst->imageData[dst->widthStep * y + x * dst->nChannels + ch]
|
|
= src->imageData[src->widthStep * yp + xp * src->nChannels + ch];
|
|
}
|
|
}
|
|
}
|
|
cvReleaseMat( &invaffine );
|
|
__CV_END__;
|
|
return dst;
|
|
}
|
|
|
|
/**
|
|
* Create a mask image for cvCreateAffineImage
|
|
*
|
|
* @param src Image. Used to get image size.
|
|
* @param affine 2 x 3 Affine transform matrix
|
|
* @param flags CV_AFFINE_SAME - Outside image coordinates are cut off
|
|
* CV_AFFINE_FULL - Fully contain the original image pixel values
|
|
* @param origin The coordinate of origin (the coordinate in original image respective to
|
|
* the transformed image origin).
|
|
* Useful when CV_AFFINE_FULL is used.
|
|
*/
|
|
CV_INLINE IplImage*
|
|
cvCreateAffineMask( const IplImage* src, const CvMat* affine,
|
|
int flags = CV_AFFINE_SAME, CvPoint* origin = NULL )
|
|
{
|
|
IplImage* orig = cvCreateImage( cvGetSize(src), IPL_DEPTH_8U, 1 );
|
|
cvSet( orig, cvScalar(1) );
|
|
IplImage* mask = cvCreateAffineImage( orig, affine, flags, origin, cvScalar(0) );
|
|
cvReleaseImage( &orig );
|
|
return mask;
|
|
}
|
|
|
|
#endif
|