您的位置:首页 > 其它

图片任意角度旋转 梯形变换 任意四边形变换

2012-04-28 16:28 369 查看
#include <opencv.hpp>
using namespace cv;
typedef int s32;
typedef long long s64;
typedef s32 cfixed;
typedef  unsigned char u8;

#define cfixed_from_int(i)		(((cfixed)(i)) << 16)
#define cfixed_from_float(x)	((cfixed)((x) * 65536.0f))
#define cfixed_from_double(d)	((cfixed)((d) * 65536.0))
#define cfixed_to_int(f)		((f) >> 16)
#define cfixed_to_float(x)		((float)((x) / 65536.0f))
#define cfixed_const_1			(cfixed_from_int(1))
#define cfixed_const_e			((cfixed)(1))
#define cfixed_const_1_m_e		(cfixed_const_1 - cfixed_const_e)
#define cfixed_const_half		(cfixed_const_1 >> 1)
#define cfixed_frac(f)			((f) & cfixed_const_1_m_e)
#define cfixed_floor(f)			((f) & (~cfixed_const_1_m_e))
#define cfixed_ceil(f)			(cfixed_floor((f) + 0xffff))
#define cfixed_mul(x, y)		((cfixed)((((s64)(x)) * (y)) >> 16))
#define cfixed_div(x, y)		((cfixed)((((s64)(x)) << 16) / (y)))
#define cfixed_const_max		((s64)0x7fffffff)
#define cfixed_const_min		(-((((s64)1) << 31)))

//定点数辅助
#define IPIXEL_EPSILON			((cfixed)(2))
#define IPIXEL_IS_SAME(a, b)	(ipixel_within_epsilon(a, b, IPIXEL_EPSILON))
#define IPIXEL_IS_ZERO(a)		(ipixel_within_epsilon(a, 0, IPIXEL_EPSILON))
#define IPIXEL_IS_ONE(a)		(IPIXEL_IS_SAME(a, cfixed_const_1))
#define IPIXEL_IS_INT(a)		(IPIXEL_IS_ZERO(cfixed_frac(a)))
#define IPIXEL_IS_UNIT(a)		(IPIXEL_IS_SAME(a, cfixed_const_1) || \
IPIXEL_IS_SAME(a, -cfixed_const_1) || \
IPIXEL_IS_ZERO(a))

enum
{
IPIXEL_FILTER_BILINEAR	= 0,	// 滤波模式:双线性过滤采样
IPIXEL_FILTER_NEAREST	= 1,	// 滤波模式:最近采样
};

// 点的定义
typedef struct
{
cfixed x;
cfixed y;
}ipixel_point_fixed_t;

// 矢量定义
typedef struct
{
cfixed vector[3];
}ipixel_vector_t;

// 矩阵定义
typedef struct
{
cfixed matrix[3][3];
}ipixel_transform_t;

// 直线定义
typedef struct
{
ipixel_point_fixed_t p1;
ipixel_point_fixed_t p2;
}ipixel_line_fixed_t;

// 像素点定义
typedef struct
{
u8 rgb[3];
}ipixel_pixel_t;

static inline s32 ipixel_within_epsilon(cfixed a, cfixed b, cfixed epsilon)
{
cfixed c = a - b;
if (c < 0) c = -c;
return c <= epsilon;
}

// 线段与y轴相交的x坐标,ceil为是否向上去整
static inline cfixed ipixel_line_fixed_x(const ipixel_line_fixed_t *l,
cfixed y, s32 ceil)
{
cfixed dx = l->p2.x - l->p1.x;
s64 ex = ((s64)(y - l->p1.y)) * dx;
cfixed dy = l->p2.y - l->p1.y;
if (ceil) ex += (dy - 1);
return l->p1.x + (cfixed)(ex / dy);
}

static inline s32 ipixel_line_span_bound(const ipixel_line_fixed_t *t, s32 y, s32 *x)
{
cfixed x1, x2, y1, y2;
s32 yt, yb;
yt = cfixed_to_int(min(t->p1.y , t->p2.y));
yb = cfixed_to_int(max(t->p1.y , t->p2.y));
if (y < yt || y >= yb) return -2;

y1 = cfixed_from_int(y);
y2 = cfixed_from_int(y) + cfixed_const_1_m_e;
x1 = cfixed_ceil(ipixel_line_fixed_x(t, y1, 0));
x2 = cfixed_ceil(ipixel_line_fixed_x(t, y2, 0));
*x = cfixed_to_int((x1 > x2)? x1 : x2);

return 0;
}

static inline s32 ipixel_lines_bound(ipixel_line_fixed_t *t, int n ,s32 y, s32 *lx, s32 *rx)
{
s32 xmin = 0x7fff, xmax = -0x7fff;
s32 x[2];

for (s32 i = 0 , j = 0; i < n;  i++)
{
if (ipixel_line_span_bound(&t[i], y, &x[j]) == 0)
{
j++;
}
}

if (j == 2)
{
*lx = min(x[0],x[1]);
*rx = max(x[0],x[1]);
return 0;
}

return -1;
}

s32 ipixel_span_fetch(const Mat *img, s32 offset, s32 line, s32 width, u8 *card, const ipixel_transform_t *t);

/* 绕任一点的旋转 变换矩阵(顺时针)
*
* 用下面的线性方程组来表示关系,求解方程组可以得到矩阵:
* |Xdst|    |  cos  sin   (1-cos)*center.x - sin*center.y| |Xsrc|
* |Ydst|    | -sin  cos   sin*center.x + (1-cos)*center.y| |Ysrc|
* |  1 |    |   0    0                 1                 | |  1 |
*/

s32 ibitmap_rotate2D(Mat *dst,Mat *src,float angle)
{
angle *= 3.1415926f/180;
cfixed  alpha = cfixed_from_float(cos(angle));
cfixed  beta  = cfixed_from_float(sin(angle));

ipixel_point_fixed_t center = {0};
center.x = cfixed_from_float(src->cols/2.0);
center.y = cfixed_from_float(src->rows/2.0);

cfixed one_sub_alpha = cfixed_const_1 - alpha;
s64 onesubalpha_mul_centerx = (s64)one_sub_alpha * center.x;
s64 onesubalpha_mul_centery = (s64)one_sub_alpha * center.y;
s64 beta_mul_centerx = (s64)beta * center.x;
s64 beta_mul_centery = (s64)beta * center.y;

ipixel_transform_t matrix = {0};
matrix.matrix[0][0] =  alpha;
matrix.matrix[0][1] =  beta;
matrix.matrix[0][2] = (onesubalpha_mul_centerx - beta_mul_centery)>>16;
matrix.matrix[1][0] =  -beta;
matrix.matrix[1][1] =  alpha;
matrix.matrix[1][2] = (onesubalpha_mul_centery + beta_mul_centerx)>>16;
matrix.matrix[2][0] =  0;
matrix.matrix[2][1] =  0;
matrix.matrix[2][2] =  cfixed_const_1;

ipixel_point_fixed_t srcQuad[4] = {0};
ipixel_point_fixed_t dstQuad[4] = {0};

srcQuad[0].x = 0;
srcQuad[0].y = 0;
srcQuad[1].x = 0;
srcQuad[1].y = cfixed_from_int(src->rows);
srcQuad[2].x = cfixed_from_int(src->cols);
srcQuad[2].y = cfixed_from_int(src->rows);
srcQuad[3].x = cfixed_from_int(src->cols);
srcQuad[3].y = 0;

cfixed minX = 0x7fffffff;
cfixed maxX = 0x80000000;
cfixed minY = 0x7fffffff;
cfixed maxY = 0x80000000;

cfixed offsetx = cfixed_from_float((dst->cols - src->cols)/2.0);
cfixed offsety = cfixed_from_float((dst->rows - src->rows)/2.0);

for (s32 i = 0; i < 4; i++)
{
dstQuad[i].x = (cfixed)(((s64)srcQuad[i].x * (s64)matrix.matrix[0][0] + (s64)srcQuad[i].y * (s64)matrix.matrix[0][1])>>16) + matrix.matrix[0][2] + offsetx;
dstQuad[i].y = (cfixed)(((s64)srcQuad[i].x * (s64)matrix.matrix[1][0] + (s64)srcQuad[i].y * (s64)matrix.matrix[1][1])>>16) + matrix.matrix[1][2] + offsety;
if(dstQuad[i].x < minX) minX = dstQuad[i].x;
if(dstQuad[i].x > maxX) maxX = dstQuad[i].x;
if(dstQuad[i].y < minY) minY = dstQuad[i].y;
if(dstQuad[i].y > maxY) maxY = dstQuad[i].y;
}

matrix.matrix[0][0] =  alpha;
matrix.matrix[0][1] =  - beta;
matrix.matrix[0][2] =  (onesubalpha_mul_centerx + beta_mul_centery - (s64)alpha*offsetx + (s64)beta*offsety)>>16;
matrix.matrix[1][0] =  beta;
matrix.matrix[1][1] =  alpha;
matrix.matrix[1][2] =  (onesubalpha_mul_centery - beta_mul_centerx - (s64)alpha*offsety - (s64)beta*offsetx)>>16;
matrix.matrix[2][0] =  0;
matrix.matrix[2][1] =  0;
matrix.matrix[2][2] =  cfixed_const_1;

//四根直线
ipixel_line_fixed_t lines[4] = {0};
for (s32 i = 0 ; i < 4 ;i++)
{
lines[i].p1 = dstQuad[i];
lines[i].p2 = dstQuad[(i+1)%4];
}

//生成扫描区域
s32 width  = cfixed_to_int(maxX - minX);
s32 height = cfixed_to_int(maxY - minY);
s32 starty = cfixed_to_int(minY);
s32 endx   = cfixed_to_int(maxX);

size_t BuffSize = dst->step;
u8 *card = (u8*)malloc(BuffSize);  //工作空间申请

// 主要绘制循环
for (s32 j = 0; j < height; j++)
{
s32 xl, xr, xw;
s32 line = j + starty;

// 取得该扫描的X轴左右对应坐标
if (ipixel_lines_bound(&lines[0],4,line, &xl, &xr) != 0)
continue;

if (xl < 0) xl = 0;
if (xr >= endx) xr = endx - 1;

xw = xr - xl;

memset(card,0,BuffSize);
ipixel_span_fetch(src, xl, line, xw, card, &matrix);
memcpy(dst->data + dst->step*line  + xl*dst->elemSize(), card, xw*dst->elemSize());
}

free(card);
return 0;
}

#define IMATRIX_SOLVE_WORKMEM(n, m) ((sizeof(s32) * n + sizeof(float) * (m * n + n * n)))

// solve X from AX=B, result is saved to X
// A(0-(n-1), 0-(n-1)), X(0-(n-1), 0-(m-1)), B(0-(n-1), 0-(m-1))
// A(i, j) = A[i * n + j], B(i, j) = B[i * m + j]
// returns zero for success, others for error.
s32 imatrix_solve_n_m(const float A[], const float B[], float X[], s32 n, s32 m)
{
// 求解矩阵所需要的临时内存大小

u8 *workmem = (u8*)malloc(IMATRIX_SOLVE_WORKMEM(n, m));
s32 *js, l, k, i, j, is, p, q;
float *a, *b, d, t;

// initialize
a = (float*)(workmem + sizeof(s32) * n);
b = (float*)(workmem + sizeof(s32) * n + sizeof(float) * n * n);

for (i = n * n - 1; i >= 0; i--)
a[i] = A[i];
for (i = m * n - 1; i >= 0; i--)
b[i] = B[i];

js = (s32*)workmem;
is = 0;
l = 1;

// solve main loop
for (k = 0; k <= n - 1; k++)
{
d = 0.0;
for (i = k; i <= n - 1; i++)
{
for (j = k; j <= n - 1; j++)
{
t = a[i * n + j];

if (t < 0)
t = -t;

if (t > d)
{
d = t;
js[k] = j;
is = i;
}
}
}

if (d + 1.0 == 1.0)
l = 0;
else
{
if (js[k] != k)
{
for (i = 0; i <= n - 1; i++)
{
p = i * n + k; q = i * n + js[k];
t = a[p]; a[p] = a[q]; a[q] = t;
}
}
if (is != k)
{
for (j = k; j <= n - 1; j++)
{
p = k * n + j;
q = is * n + j;
t = a[p];
a[p] = a[q];
a[q] = t;
}
for (j = 0; j <= m - 1; j++)
{
p = k * m + j;
q = is * m + j;
t = b[p];
b[p] = b[q];
b[q] = t;
}
}
}

// check if no result
if (l == 0)
{
return -1;
}

d = a[k * n + k];

for (j = k + 1; j <= n - 1; j++)
{
p = k * n + j;
a[p] = a[p] / d;
}

for (j = 0; j <= m - 1; j++)
{
p = k * m + j;
b[p] = b[p] / d;
}

for (j = k + 1; j <= n - 1; j++)
{
for (i = 0; i <= n - 1; i++)
{
p = i * n + j;
if (i != k)
{
a[p] = a[p] - a[i * n + k] * a[k * n + j];
}
}
}

for (j = 0; j <= m-1; j++)
{
for (i = 0; i <= n - 1; i++)
{
p = i * m + j;
if (i != k)
{
b[p] = b[p] - a[i * n + k] * b[k * m + j];
}
}
}
}

for (k = n - 1; k >= 0; k--)
{
if (js[k] != k)
{
for (j = 0; j <= m - 1; j++)
{
p = k * m + j; q = js[k] * m + j;
t = b[p]; b[p] = b[q]; b[q] = t;
}
}
}

for (i = m * n - 1; i >= 0; i--)
X[i] = b[i];

free(workmem);
return 0;
}

/* 计算透视投影的变换矩阵
*      c00*xi + c01*yi + c02
* ui = ---------------------
*      c20*xi + c21*yi + c22
*
*      c10*xi + c11*yi + c12
* vi = ---------------------
*      c20*xi + c21*yi + c22
*
* 用下面的线性方程组来表示关系,求解方程组可以得到矩阵:
* / x0 y0  1  0  0  0 -x0*u0 -y0*u0 \ /c00\ /u0\
* | x1 y1  1  0  0  0 -x1*u1 -y1*u1 | |c01| |u1|
* | x2 y2  1  0  0  0 -x2*u2 -y2*u2 | |c02| |u2|
* | x3 y3  1  0  0  0 -x3*u3 -y3*u3 |.|c10|=|u3|,
* |  0  0  0 x0 y0  1 -x0*v0 -y0*v0 | |c11| |v0|
* |  0  0  0 x1 y1  1 -x1*v1 -y1*v1 | |c12| |v1|
* |  0  0  0 x2 y2  1 -x2*v2 -y2*v2 | |c20| |v2|
* \  0  0  0 x3 y3  1 -x3*v3 -y3*v3 / \c21/ \v3/
*
* 其中:
*   cij - 变换剧照的元素, c22 = 1
*/
s32 itransform_perspective(float m[], const float src[], const float dst[])
{
float a[8][8], b[8], x[8];
s32 i;

for (i = 0; i < 4; i++)
{
a[i][0] = a[i + 4][3] = src[i * 2 + 0];
a[i][1] = a[i + 4][4] = src[i * 2 + 1];
a[i][2] = a[i + 4][5] = 1;
a[i][3] = a[i][4] = a[i][5] = 0;
a[i + 4][0] = a[i + 4][1] = a[i + 4][2] = 0;
a[i][6] = -src[i * 2 + 0] * dst[i * 2 + 0];
a[i][7] = -src[i * 2 + 1] * dst[i * 2 + 0];
a[i + 4][6] = -src[i * 2 + 0] * dst[i * 2 + 1];
a[i + 4][7] = -src[i * 2 + 1] * dst[i * 2 + 1];
b[i] = dst[i * 2 + 0];
b[i + 4] = dst[i * 2 + 1];
}

if (imatrix_solve_n_m(&a[0][0], b, x, 8, 1) != 0)
return -1;

for (i = 0; i < 8; i++) m[i] = x[i];
m[8] = 1.0;

return 0;
}

// 初始化透视矩阵
s32 ipixel_transform_init_perspective(ipixel_transform_t *matrix,
const  ipixel_point_fixed_t *src,
const  ipixel_point_fixed_t *dst)
{
float fsrc[8];
float fdst[8];
float fmat[9];
s32 i, j;
s64 n;

for (i = 0; i < 4; i++)
{
fsrc[i * 2 + 0] = cfixed_to_float(src[i].x);
fsrc[i * 2 + 1] = cfixed_to_float(src[i].y);
fdst[i * 2 + 0] = cfixed_to_float(dst[i].x);
fdst[i * 2 + 1] = cfixed_to_float(dst[i].y);
}

if (itransform_perspective(fmat, fsrc, fdst) != 0)
return -1;

for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
n = ((s64)( fmat[i * 3 + j] * 65536.0));  //注意
if (n < cfixed_const_min || n > cfixed_const_max)
{
return -2;
}
matrix->matrix[i][j] = (cfixed)n;
}
}
return 0;
}

s32 ibitmap_quadtransform(Mat *dst,Mat *src,ipixel_point_fixed_t* p )
{
//四根直线
ipixel_line_fixed_t lines[4] = {0};
for (s32 i = 0 ; i < 4 ;i++)
{
lines[i].p1 = p[i];
lines[i].p2 = p[(i+1)%4];
}

cfixed minX = 0x7fffffff;
cfixed maxX = 0x80000000;
cfixed minY = 0x7fffffff;
cfixed maxY = 0x80000000;
for (s32 i = 0; i < 4; i++)
{
if(p[i].x < minX) minX = p[i].x;
if(p[i].x > maxX) maxX = p[i].x;
if(p[i].y < minY) minY = p[i].y;
if(p[i].y > maxY) maxY = p[i].y;
}
//生成扫描区域
s32 width  = cfixed_to_int(maxX - minX);
s32 height = cfixed_to_int(maxY - minY);
s32 starty = cfixed_to_int(minY);
s32 endx   = cfixed_to_int(maxX);

size_t BuffSize = dst->step;
u8 *card = (u8*)malloc(BuffSize);  //工作空间申请

ipixel_point_fixed_t srcQuad[4];
srcQuad[0].x = 0;
srcQuad[0].y = 0;
srcQuad[1].x = 0;
srcQuad[1].y = cfixed_from_int(src->rows);
srcQuad[2].x = cfixed_from_int(src->cols);
srcQuad[2].y = cfixed_from_int(src->rows);
srcQuad[3].x = cfixed_from_int(src->cols);
srcQuad[3].y = 0;

//计算变换矩阵
ipixel_transform_t matrix = {0};

if (ipixel_transform_init_perspective(&matrix, p,&srcQuad[0]) != 0)
return -8;

// 主要绘制循环
for (s32 j = 0; j < height; j++)
{
s32 xl, xr, xw;
s32 line = j + starty;

// 取得该扫描的X轴左右对应坐标
if (ipixel_lines_bound(&lines[0],4,line, &xl, &xr) != 0)
continue;

if (xl < 0) xl = 0;
if (xr >= endx) xr = endx - 1;

xw = xr - xl;

memset(card,0,BuffSize);
ipixel_span_fetch(src, xl, line, xw, card, &matrix);
memcpy(dst->data + dst->step*line  + xl*dst->elemSize(), card, xw*dst->elemSize());
}

free(card);
return 0;
}

// 矩阵同点相乘: matrix * vector
s32 ipixel_transform_point(const ipixel_transform_t *t,ipixel_vector_t *vector)
{
ipixel_vector_t result = {0};
s64 partial;
s64 v;
s32 i, j;

for (j = 0; j < 3; j++)
{
v = 0;
for (i = 0; i < 3; i++)
{
partial = ((s64)t->matrix[j][i])*((s64)vector->vector[i]);
v += partial >> 16 ;
}
if (v > cfixed_const_max || v < cfixed_const_min)
return -1;
result.vector[j] = (cfixed)v;
}

*vector = result;

if (vector->vector[2] == 0)
return -2;

return 0;
}

void ibitmap_fetch_pixel(const Mat* img , ipixel_pixel_t* pr ,cfixed x, cfixed y)
{
s32 x0 = (x < 0)? 0 : (x >= img->cols)? (img->cols - 1) : x;
s32 y0 = (y < 0)? 0 : (y >= img->rows)? (img->rows - 1) : y;

u8* pdata = img->data + y0*img->step + x0 * img->elemSize();

pr->rgb[0] = pdata[0];
pr->rgb[1] = pdata[1];
pr->rgb[2] = pdata[2];
}

void ibitmap_fetch_pixel_bilinear(const Mat* img , ipixel_pixel_t* pr ,cfixed x, cfixed y)
{
cfixed x1 = x - cfixed_const_1 / 2;
cfixed y1 = y - cfixed_const_1 / 2;
cfixed distx = (x1 >> 8) & 0xff;
cfixed disty = (y1 >> 8) & 0xff;
x1 = cfixed_to_int(x1);
y1 = cfixed_to_int(y1);
s32 x2 = x1 + 1;
s32 y2 = y1 + 1;

ipixel_pixel_t c[2][2] = {0};
ibitmap_fetch_pixel(img ,&c[0][0],x1 ,y1 );
ibitmap_fetch_pixel(img ,&c[0][1],x2 ,y1 );
ibitmap_fetch_pixel(img ,&c[1][0],x1 ,y2 );
ibitmap_fetch_pixel(img ,&c[1][1],x2 ,y2 );

s32 distxy = distx * disty;
s32 distxiy = (distx << 8) - distxy;	/* distx * (256 - disty) */
s32 distixy = (disty << 8) - distxy;	/* disty * (256 - distx) */
s32 distixiy = 256 * 256 - (disty << 8) - (distx << 8) + distxy;		/* (256 - distx) * (256 - disty) */

for(s32 i = 0 ; i < 3 ; i++)
{
pr->rgb[i] = cfixed_to_int(c[0][0].rgb[i] * distixiy + c[0][1].rgb[i] * distxiy +c[1][0].rgb[i] * distixy + c[1][1].rgb[i] * distxy);
}
}

s32 ipixel_span_fetch(const Mat *img, s32 offset, s32 line, s32 width, u8 *card, const ipixel_transform_t *t )
{
ipixel_vector_t vec, step;
vec.vector[0] = cfixed_from_int(offset) + cfixed_const_half;
vec.vector[1] = cfixed_from_int(line) + cfixed_const_half;
vec.vector[2] = cfixed_const_1;

if (t != NULL)
{
if (ipixel_transform_point(t, &vec) != 0)
return -12;

step.vector[0] = t->matrix[0][0];
step.vector[1] = t->matrix[1][0];
step.vector[2] = t->matrix[2][0];
}
else
{
step.vector[0] = cfixed_const_1;
step.vector[1] = 0;
step.vector[2] = 0;
}

if (IPIXEL_IS_ZERO(step.vector[2]))
{
step.vector[2] = 0;

if (IPIXEL_IS_ONE(vec.vector[2]))
vec.vector[2] = cfixed_const_1;

if (vec.vector[2] != cfixed_const_1)
{
cfixed w = vec.vector[2];
vec.vector[0] = cfixed_div(vec.vector[0], w);
vec.vector[1] = cfixed_div(vec.vector[1], w);
vec.vector[2] = cfixed_const_1;
step.vector[0] = cfixed_div(step.vector[0], w);
step.vector[1] = cfixed_div(step.vector[1], w);
step.vector[2] = cfixed_div(step.vector[2], w);
}
}

cfixed u, v, w, du, dv, dw, x, y;
u = vec.vector[0];
v = vec.vector[1];
w = vec.vector[2];
du = step.vector[0];
dv = step.vector[1];
dw = step.vector[2];

u8* pdata = NULL;
ipixel_pixel_t pixel = {0};
s32 filter = IPIXEL_FILTER_BILINEAR;  //IPIXEL_FILTER_NEAREST
if (filter == IPIXEL_FILTER_BILINEAR)
{
if (w == cfixed_const_1 && dw == 0)
{
for (; width > 0; width--)
{
ibitmap_fetch_pixel_bilinear(img , &pixel ,u, v);
memcpy(card , &pixel , img->elemSize());
card += img->elemSize();
u += du;
v += dv;
w += dw;
}
}
else
{
for (; width > 0;  width--)
{
if (w != 0)
{
x = cfixed_div(u, w);
y = cfixed_div(v, w);
}
else
{
x = 0, y = 0;
}
ibitmap_fetch_pixel_bilinear(img , &pixel ,x, y );
memcpy(card , &pixel , img->elemSize());
card += img->elemSize();
u += du;
v += dv;
w += dw;
}
}
}
else//IPIXEL_FILTER_NEAREST
{
if (w == cfixed_const_1 && dw == 0)
{
for (; width > 0; width--)
{
ibitmap_fetch_pixel(img , &pixel ,u, v );
memcpy(card , &pixel , img->elemSize());
card += img->elemSize();
u += du;
v += dv;
w += dw;
}
}
else
{
for (; width > 0;  width--)
{
if (w != 0)
{
x = cfixed_div(u, w);
y = cfixed_div(v, w);
}
else
{
x = 0, y = 0;
}

s32 x0 = cfixed_to_int(x - cfixed_const_e);
s32 y0 = cfixed_to_int(y - cfixed_const_e);

ibitmap_fetch_pixel(img,&pixel,x0,y0);
memcpy(card , &pixel , 3);
card += img->elemSize();
u += du;
v += dv;
w += dw;
}
}
}
return 0;
}

typedef struct
{
s32 bottom;
s32 top;
s32 bottom_startx;
s32 bottom_endx;
s32 top_startx;
s32 top_endx;
}VTrapeParam_t;

void inline ibitmap_Linearfill(u8* dst , u8* src , cfixed s , cfixed d)
{
if (s > d)
{
cfixed step_x = cfixed_div(s,d);
s32 d_int = cfixed_to_int(d);
cfixed fixed_src = 0;
for (s32 i = 0; i < d_int ; i++)
{
memcpy(dst , src + 3*cfixed_to_int(fixed_src) , 3 );
fixed_src += step_x;
dst += 3;
}
}
else
{
cfixed step_x = cfixed_div(d,s);
s32 s_int = cfixed_to_int(s);
s32 size = 3*cfixed_to_int(cfixed_ceil(step_x));
cfixed fixed_dst = 0;

for (s32 i = 0; i < s_int ; i++)
{
memcpy(dst +  3 * cfixed_to_int(fixed_dst), src  , size);
fixed_dst += step_x;
src += 3;
}

}

}
void ibitmap_HTrapetransform( Mat *dst,Mat *src,VTrapeParam_t *thiz)
{
s32 bottom         = thiz->bottom;
s32 top			   = thiz->top;
s32 bottom_startx  = thiz->bottom_startx;
s32 bottom_endx    = thiz->bottom_endx;
s32 top_startx     = thiz->top_startx;
s32 top_endx       = thiz->top_endx;

u8* pSrcData = src->data;
u8* pDstData = dst->data;
u8* pSrc = src->data;
u8* pDst = dst->data;

cfixed starty_dst = cfixed_from_int(top);
cfixed starty_src = cfixed_from_int(0);
cfixed endy_dst   = cfixed_from_int(bottom);
cfixed endy_src   = cfixed_from_int(src->rows);
cfixed y_dst      = starty_dst;
cfixed y_src      = starty_src;
cfixed startx_dst = cfixed_from_int(top_startx) ;
cfixed endx_dst   = cfixed_from_int(top_endx) ;
cfixed endx_src   = cfixed_from_int(src->cols);

cfixed src_dy     = cfixed_div(endy_src - starty_src,endy_dst - starty_dst);
cfixed dst_dx1    = cfixed_div(cfixed_from_int(bottom_startx - top_startx),cfixed_from_int(bottom - top));
cfixed dst_dx2    = cfixed_div(cfixed_from_int(bottom_endx - top_endx),cfixed_from_int(bottom - top));

while(y_dst < endy_dst && y_src < endy_src)
{
cfixed x_dst = startx_dst;
cfixed x_src = 0;
cfixed dx_src =  cfixed_div(endx_src ,endx_dst - startx_dst);

pDst = pDstData + cfixed_to_int(y_dst)*dst->step + cfixed_to_int(startx_dst)*3;
pSrc = pSrcData + cfixed_to_int(y_src)*src->step ;

ibitmap_Linearfill(pDst , pSrc  , endx_src , endx_dst - startx_dst);

startx_dst += dst_dx1;
endx_dst   += dst_dx2;
y_dst += cfixed_const_1;
y_src += src_dy ;
}
}

s32 main()
{
Mat src = imread("res_fish.bmp");
imshow("Src" , src);

//水平梯形变换
Mat HTrapedst = Mat::zeros(600,800, CV_8UC3);    //创建目标图像
VTrapeParam_t tParam = {0};
tParam.bottom = 500;
tParam.top = 100;
tParam.top_startx = 200;
tParam.top_endx = 350;
tParam.bottom_startx = 10;
tParam.bottom_endx = 600;
ibitmap_HTrapetransform(&HTrapedst , &src , &tParam);
imshow("HTrapedst" , HTrapedst);

//任意四边形变换
Mat Quaddst = Mat::zeros(600,800, CV_8UC3);    //创建目标图像
ipixel_point_fixed_t dstQuad[4] = {0};
dstQuad[0].x = cfixed_from_int(10);
dstQuad[0].y = cfixed_from_int(70);
dstQuad[1].x = cfixed_from_int(200);
dstQuad[1].y = cfixed_from_int(230);
dstQuad[2].x = cfixed_from_int(250);
dstQuad[2].y = cfixed_from_int(100);
dstQuad[3].x = cfixed_from_int(130);
dstQuad[3].y = cfixed_from_int(20);
ibitmap_quadtransform(&Quaddst, &src,&dstQuad[0]);
imshow("Quaddst" , Quaddst);

s32 dst_Side_length = sqrt((float)src.cols*src.cols+(float)src.rows*src.rows)+1;
s32 angle = 0;
while (1)
{
++angle %= 360;
Mat Rotatedst = Mat::zeros(dst_Side_length,dst_Side_length, CV_8UC3);    //创建目标图像
ibitmap_rotate2D(&Rotatedst,&src,angle);
imshow("Dstimage", Rotatedst);
waitKey(40);
}
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: