图片任意角度旋转 梯形变换 任意四边形变换
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); } }
相关文章推荐
- 使用.net(C#)处理图片之:旋转图片任意角度
- MFC中BMP图片旋转任意角度、用于绘制模拟时钟表针
- C#实现任意角度旋转图片(方法2)
- C# 图片处理之:旋转图片任意角度 .
- MFC中BMP图片旋转任意角度、用于绘制模拟时钟表针
- JQuery插件让图片旋转任意角度
- java 实现图片任意角度旋转,及背景透明
- C#实现任意角度旋转图片(方法1)
- 图片任意角度旋转
- C# 图片处理之:旋转图片任意角度
- JQuery插件让图片旋转任意角度且代码极其简单
- JQuery插件让图片旋转任意角度且代码极其简单 - 摘自网友
- 让图片旋转任意角度及JQuery插件使用介绍
- Java实现图片内容无损任意角度旋转
- JAVA 按任意角度旋转图片,并生成新的旋转后图片(转自:http://www.hackchina.com/r/21265/RotateImage.java__html)
- Java实现图片内容无损任意角度旋转
- C# 图片处理之:旋转图片任意角度
- Java实现图片内容无损任意角度旋转
- JAVA对图片的任意角度旋转,以及镜像操作
- Java基础(五):Java实现图片无损任意角度旋转