//最近邻插值 public Color nearest_interp(myMat.myCoor source_p) { double i = (int)System.Math.Round(source_p.i); double j = (int)System.Math.Round(source_p.j); return(inputImg.getRGB(new myMat.myCoor(i, j))); }
public myMat.myCoor bend_source_coor(myMat.myCoor aim_p, myMat.myCoor mid_p, double a_max, double radius) { /* * 弯曲变换,输入目标图中的坐标,返回原图坐标 * aim_p: 目标图坐标 * mid_p: 中点坐标 * a_max: 最大旋转角度,弧度制 * radius: 旋转半径 */ double dis = aim_p.getDis(mid_p); if (dis >= radius) { return(aim_p); } double a = a_max * (radius - dis) / radius; int x_ = (int)(aim_p.j - mid_p.j); int y_ = (int)(aim_p.i - mid_p.i); myMat.myCoor ord = new myMat.myCoor(); ord.j = x_ * System.Math.Cos(a) - y_ * System.Math.Sin(a); ord.j = ord.j + mid_p.j; ord.i = x_ * System.Math.Sin(a) + y_ * System.Math.Cos(a); ord.i = ord.i + mid_p.i; return(ord); }
//双线性插值 public Color bilinear_interp(myMat.myCoor source_p) { int x1 = (int)System.Math.Floor(source_p.i); int y1 = (int)System.Math.Floor(source_p.j); int x2 = x1 + 1; int y2 = y1 + 1; Byte[] f11 = inputImg.getRGB_Byte(new myMat.myCoor(x1, y1)); Byte[] f12 = inputImg.getRGB_Byte(new myMat.myCoor(x1, y2)); Byte[] f21 = inputImg.getRGB_Byte(new myMat.myCoor(x2, y1)); Byte[] f22 = inputImg.getRGB_Byte(new myMat.myCoor(x2, y2)); double[] fxy1 = new double[3]; double[] fxy2 = new double[3]; double[] fxy = new double[3]; for (int k = 0; k < 3; k++) { fxy1[k] = (x2 - source_p.i) / (x2 - x1) * (double)f11[k] + (source_p.i - x1) / (x2 - x1) * (double)f21[k]; fxy2[k] = (x2 - source_p.i) / (x2 - x1) * (double)f12[k] + (source_p.i - x1) / (x2 - x1) * (double)f22[k]; } for (int k = 0; k < 3; k++) { fxy[k] = (y2 - source_p.j) / (y2 - y1) * (double)fxy1[k] + (source_p.j - y1) / (y2 - y1) * (double)fxy2[k]; } return(inputImg.getRGB_fromB(fxy)); }
//TPS变换得到目标图中第i行i列坐标对应原图中的坐标 public myMat.myCoor TPS_get_sourceCoor(int i, int j) { double source_x = 0, source_y = 0; for (int k = 0; k < point_num; k++) { double dis = System.Math.Pow(i - aim_ps[k, 0], 2) + System.Math.Pow(j - aim_ps[k, 1], 2); if (dis == 0) { dis += 1e-16; } double L_k = dis * System.Math.Log(dis) / 2; source_x += L_k * W[k, 0]; source_y += L_k * W[k, 1]; } source_x += W[point_num, 0] * 1; source_x += W[point_num + 1, 0] * i; source_x += W[point_num + 2, 0] * j; source_y += W[point_num, 1] * 1; source_y += W[point_num + 1, 1] * i; source_y += W[point_num + 2, 1] * j; myMat.myCoor sourceCoor = new myMat.myCoor(source_x, source_y); return(sourceCoor); }
//旋转变换 返回原图中对应坐标点 public myMat.myCoor Turn_get_sourceCoor(int i, int j, double turn_angle) { double x, y; x = i * System.Math.Cos(turn_angle) - j * System.Math.Sin(turn_angle); y = i * System.Math.Sin(turn_angle) + j * System.Math.Cos(turn_angle); myMat.myCoor sourceCoor = new myMat.myCoor(x, y); return(sourceCoor); }
public Color interp(myMat.myCoor source_p, string interp_method) { if (interp_method == "最近邻") { return(nearest_interp(source_p)); } else if (interp_method == "双线性") { return(bilinear_interp(source_p)); } else { return(bicubic_interp(source_p)); } }
public myMat.myCoor ball_source_coor(myMat.myCoor aim_p, myMat.myCoor mid_p, double radius, int direction = 1) { /* * 球形畸变,输入目标图中的坐标,返回原图坐标 * aim_p: 目标图坐标 * mid_p: 中点坐标 * radius: 畸变半径 */ double dis = aim_p.getDis(mid_p); int x_ = (int)(aim_p.j - mid_p.j); int y_ = (int)(aim_p.i - mid_p.i); myMat.myCoor ord = new myMat.myCoor(); if (direction > 0) //桶形畸变 { ord.j = radius / dis * System.Math.Asin(dis / radius) * x_; ord.i = radius / dis * System.Math.Asin(dis / radius) * y_; } else //枕形畸变 { ord.j = dis / radius / System.Math.Asin(dis / radius) * x_; ord.i = dis / radius / System.Math.Asin(dis / radius) * y_; } ord.j = ord.j + mid_p.j; ord.i = ord.i + mid_p.i; if (double.IsNaN(ord.i)) { ord.i = inputImg.height + 1000; } if (double.IsNaN(ord.j)) { ord.j = inputImg.width + 1000; } return(ord); }
public void bend_distort(double a_max, double radius, string interp_method = "最近邻") { /* * 弯曲变换,将结果赋予resultImg * a_max: 最大旋转角度,角度制 * radius: 旋转半径 */ resultImg = new myMat(); double a_max_arc = a_max * System.Math.PI / 180; myMat.myCoor mid_p = new myMat.myCoor(inputImg.height / 2, inputImg.width / 2); resultImg.init_bytes(inputImg.height, inputImg.width); for (int i = 0; i < inputImg.height; i++) { for (int j = 0; j < inputImg.width; j++) { myMat.myCoor sourceCoor = bend_source_coor(new myMat.myCoor(i, j), mid_p, a_max_arc, radius); Color c = interp(sourceCoor, interp_method); resultImg.set_rgb(c, new myMat.myCoor(i, j)); } } }
//使用参数矩阵W求得目标图 public void get_result_img(string interp_method) { myMat.myCoor source_leftUp_point = new myMat.myCoor(in_i: sourceFace_distort.inputImg.height, in_j: sourceFace_distort.inputImg.width); //初始化为右下角点 myMat.myCoor source_leftDown_point = new myMat.myCoor(in_i: 0, in_j: sourceFace_distort.inputImg.width); //初始化为右上角点 leftUp_point = new myMat.myCoor(); //初始化为右下角点 leftDown_point = new myMat.myCoor(); //初始化为右上角点 myMat.myCoor vir_leftUp_point = new myMat.myCoor(0, 0); myMat.myCoor vir_leftDown_point = new myMat.myCoor(sourceFace_distort.inputImg.height, 0); sourceFace_distort.resultImg = new myMat(); sourceFace_distort.resultImg.init_bytes(sourceFace_distort.inputImg.height, sourceFace_distort.inputImg.width); for (int i = 0; i < sourceFace_distort.inputImg.height; i++) { for (int j = 0; j < sourceFace_distort.inputImg.width; j++) { //得到目标图中第i行i列坐标对应原图中的坐标 myMat.myCoor sourceCoor = TPS_get_sourceCoor(i, j); if (sourceCoor.i >= 0 && sourceCoor.j >= 0 && sourceCoor.i < sourceFace_distort.inputImg.height && sourceCoor.j < sourceFace_distort.inputImg.width) { if (myMat.myCoor.getDis(sourceCoor, vir_leftUp_point) < myMat.myCoor.getDis(source_leftUp_point, vir_leftUp_point)) { source_leftUp_point.i = sourceCoor.i; source_leftUp_point.j = sourceCoor.j; leftUp_point.i = i; leftUp_point.j = j; } if (myMat.myCoor.getDis(sourceCoor, vir_leftDown_point) < myMat.myCoor.getDis(source_leftDown_point, vir_leftDown_point)) { source_leftDown_point.i = sourceCoor.i; source_leftDown_point.j = sourceCoor.j; leftDown_point.i = i; leftDown_point.j = j; } } Color c = sourceFace_distort.interp(sourceCoor, interp_method); sourceFace_distort.resultImg.set_rgb(c, new myMat.myCoor(i, j)); } } }
//双三次插值 public Color bicubic_interp(myMat.myCoor source_p) { //x y坐标的小数部分 int x1 = (int)System.Math.Floor(source_p.i); int y1 = (int)System.Math.Floor(source_p.j); double dx = source_p.i - x1; double dy = source_p.j - y1; double[] result = new double[3] { 0, 0, 0 }; double k_sum = 0; for (int x = -1; x <= 2; x++) { for (int y = -1; y <= 2; y++) { double dis_x = System.Math.Abs(dx - x); double dis_y = System.Math.Abs(dy - y); double kx = bsp_bicubic_k(dis_x); double ky = bsp_bicubic_k(dis_y); Byte[] fxy = inputImg.getRGB_Byte(new myMat.myCoor(x1 + x, y1 + y)); k_sum += kx * ky; for (int k = 0; k < 3; k++) { result[k] += fxy[k] * kx * ky; } } } for (int k = 0; k < 3; k++) { result[k] /= k_sum; } return(inputImg.getRGB_fromB(result)); }
public void ball_distort(double height, string interp_method = "最近邻") { /* * 球形变换,将结果赋予resultImg * height: 球形变换的高度参数 */ resultImg = new myMat(); double height_abs = System.Math.Abs(height); double m = System.Math.Sqrt(inputImg.height * inputImg.height + inputImg.width * inputImg.width) / 2; double radius = (height * height + m * m) / 2 / height_abs; myMat.myCoor mid_p = new myMat.myCoor(inputImg.height / 2, inputImg.width / 2); resultImg.init_bytes(inputImg.height, inputImg.width); for (int i = 0; i < inputImg.height; i++) { for (int j = 0; j < inputImg.width; j++) { myMat.myCoor sourceCoor = ball_source_coor(new myMat.myCoor(i, j), mid_p, radius, direction: (int)(height / height_abs)); Color c = interp(sourceCoor, interp_method); resultImg.set_rgb(c, new myMat.myCoor(i, j)); } } }
//切除黑边 public void BlackCut_tran(string interp_method = "最近邻") { blackCut_distort = new Pic_distort(); blackCut_distort.inputImg = new myMat(); blackCut_distort.inputImg.getData_Mat(sourceFace_distort.resultImg); blackCut_distort.resultImg = new myMat(); blackCut_distort.resultImg.init_bytes(blackCut_distort.inputImg.height, blackCut_distort.inputImg.width); /*Bitmap bm = blackCut_distort.inputImg.img2Bitmap(); * Image<Bgr, byte> draw_img = new Image<Bgr, byte>(bm); * draw_img.Draw(new Cross2DF(new PointF((int)leftUp_point.j, (int)leftUp_point.i), 10, 10), new Bgr(0, 0, 255), 2); * draw_img.Draw(new Cross2DF(new PointF((int)leftDown_point.j, (int)leftDown_point.i), 10, 10), new Bgr(0, 0, 255), 2); * * CvInvoke.Imshow("a", draw_img); * CvInvoke.WaitKey();*/ double turn_angle = System.Math.Atan2((leftDown_point.j - leftUp_point.j), (leftDown_point.i - leftUp_point.i)); double height_scale = myMat.myCoor.getDis(leftUp_point, leftDown_point) / blackCut_distort.resultImg.height; for (int i = 0; i < blackCut_distort.inputImg.height; i++) { for (int j = 0; j < blackCut_distort.inputImg.width; j++) { if (i == blackCut_distort.inputImg.height - 3 && j == 0) { int a = 0; } myMat.myCoor sourceCoor = Turn_get_sourceCoor(i, j, turn_angle); sourceCoor.i *= height_scale; sourceCoor.j *= height_scale; sourceCoor.i += (int)leftUp_point.i; sourceCoor.j += (int)leftUp_point.j; Color c = blackCut_distort.interp(sourceCoor, interp_method); blackCut_distort.resultImg.set_rgb(c, new myMat.myCoor(i, j)); } } /*Bitmap bm2 = blackCut_distort.resultImg.img2Bitmap(); * Image<Bgr, byte> draw_img2 = new Image<Bgr, byte>(bm2); * * CvInvoke.Imshow("a", draw_img2); * CvInvoke.WaitKey();*/ int min_y, max_y, max_x, min_x; blackCut_getIJ(out min_y, out max_y, out min_x, out max_x); int new_height = max_x - min_x + 1; int new_width = max_y - min_y + 1; for (int i = 0; i < new_height; i++) { for (int j = 0; j < new_width; j++) { int i_cut = min_x + i; int j_cut = min_y + j; Color source_color = blackCut_distort.resultImg.getRGB(new myMat.myCoor(i_cut, j_cut)); blackCut_distort.resultImg.set_rgb(source_color, new myMat.myCoor(i, j)); } } blackCut_distort.resultImg.height = new_height; blackCut_distort.resultImg.width = new_width; }