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.

171 lines
6.5 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_CROPIMAGEROI_INCLUDED
#define CV_CROPIMAGEROI_INCLUDED
#include "cv.h"
#include "cvaux.h"
#include "cxcore.h"
#define _USE_MATH_DEFINES
#include <math.h>
#include "cvrect32f.h"
#include "cvcreateaffine.h"
#include "cvcreateaffineimage.h"
// CVAPI(void) cvPutImageROI( const IplImage* src,
// IplImage* dst,
// CvRect32f rect32f = cvRect32f(0,0,1,1,0),
// CvPoint2D32f shear = cvPoint2D32f(0,0),
// const IplImage* mask = NULL,
// bool circumscribe = 0 );
/**
* Put a source image on the specified region on a target image
*
* Use CvBox32f to define rotation center as the center of rectangle,
* and use cvRect32fBox32( box32f ) to pass argument.
*
* @param src The source image
* @param dst The target image
* @param rect32f The rectangle region (x,y,width,height) to put
* the rotation angle in degree where the rotation center is (x,y)
* @param shear The shear deformation parameter shx and shy
* @param mask The mask image
* @param circumscribe Put a circular (ellipsoidal) image as a circumscribed
* circle (ellipsoid) rather than a inscribed circle (ellipsoid)
* @return CVAPI(void)
*/
CVAPI(void) cvPutImageROI( const IplImage* src,
IplImage* dst,
CvRect32f rect32f CV_DEFAULT(cvRect32f(0,0,1,1,0)),
CvPoint2D32f shear CV_DEFAULT(cvPoint2D32f(0,0)),
const IplImage* mask CV_DEFAULT(NULL),
bool circumscribe CV_DEFAULT(0) )
{
CvRect rect;
float tx, ty, sx, sy, angle;
IplImage* _src = NULL;
IplImage* _mask = NULL;
CV_FUNCNAME( "cvPutImageROI" );
__CV_BEGIN__;
rect = cvRectFromRect32f( rect32f );
angle = rect32f.angle;
CV_ASSERT( rect.width > 0 && rect.height > 0 );
CV_ASSERT( src->depth == dst->depth );
CV_ASSERT( src->nChannels == dst->nChannels );
if( mask != NULL )
CV_ASSERT( src->width == mask->width && src->height == mask->height );
if( circumscribe )
{
CvBox32f box32f = cvBox32fFromRect32f( rect32f );
// width and height from center (inscribed ellipsoid's a and b parameters)
float a = box32f.width / 2.0;
float b = box32f.height / 2.0;
// diagonal distance to the corner of rectangle from center
float d = sqrt( a * a + b * b );
// get distance to the intersectional point of inscribed ellipsoid
// line with rectangle's diagonal line from center
float cost = a / d;
float sint = b / d;
float c = sqrt( pow( a * cost, 2 ) + pow( b * sint, 2 ) );
// this ratio enables to make circumscribed ellipsoid
float ratio = d / c;
box32f.width *= ratio;
box32f.height *= ratio;
// ellipsoidal paramter to rectangle parameter
rect32f = cvRect32fFromBox32f( box32f );
rect = cvRectFromRect32f( rect32f );
}
_src = (IplImage*)src;
_mask = (IplImage*)mask;
if( rect.width != src->width && rect.height != src->height )
{
_src = cvCreateImage( cvSize( rect.width, rect.height ), src->depth, src->nChannels );
cvResize( src, _src );
if( mask != NULL )
{
_mask = cvCreateImage( cvSize( rect.width, rect.height ), mask->depth, mask->nChannels );
cvResize( mask, _mask );
}
}
if( angle == 0 && shear.x == 0 && shear.y == 0 &&
rect.x >= 0 && rect.y >= 0 &&
rect.x + rect.width < dst->width && rect.y + rect.height < dst->height )
{
cvSetImageROI( dst, rect );
cvCopy( _src, dst, _mask );
cvResetImageROI( dst );
}
else
{
if( _mask == NULL )
{
_mask = cvCreateImage( cvGetSize(_src), IPL_DEPTH_8U, 1 );
cvSet( _mask, cvScalar(1) );
}
CvMat* affine = cvCreateMat( 2, 3, CV_32FC1 );
tx = 0;
ty = 0;
sx = rect32f.width / (float)_src->width;
sy = rect32f.height / (float)_src->height;
angle = rect32f.angle;
cvCreateAffine( affine, cvRect32f( tx, ty, sx, sy, angle ), shear );
CvPoint origin;
IplImage* srctrans = cvCreateAffineImage( _src, affine, CV_AFFINE_FULL, &origin, CV_RGB(0,0,0) );
IplImage* masktrans = cvCreateAffineImage( _mask, affine, CV_AFFINE_FULL, NULL, cvScalar(0) );
for( int xp = 0; xp < srctrans->width; xp++ )
{
int x = xp + rect.x + origin.x;
for( int yp = 0; yp < srctrans->height; yp++ )
{
int y = yp + rect.y + origin.y;
if( x < 0 || x >= dst->width || y < 0 || y >= dst->height ) continue;
if( CV_IMAGE_ELEM( masktrans, uchar, yp, xp ) == 0 ) continue;
for( int ch = 0; ch < srctrans->nChannels; ch++ )
{
dst->imageData[dst->widthStep * y + x * dst->nChannels + ch]
= srctrans->imageData[srctrans->widthStep * yp + xp * srctrans->nChannels + ch];
}
}
}
cvReleaseMat( &affine );
cvReleaseImage( &srctrans );
cvReleaseImage( &masktrans );
}
if( mask != _mask )
cvReleaseImage( &_mask );
if( src != _src )
cvReleaseImage( &_src );
__CV_END__;
}
#endif