Middlebury立体匹配源码总结

优化方法

图像可否预处理

代价计算可否采用BT方式

可选代价计算方法

可否代价聚合

可否MinFilter优化原始代价

WTA-Box

可以

可以

AD/SD

可以,聚合尺寸可变,迭代次数1次

可以

WTA-Binomial

可以

可以

AD/SD

可以,聚合尺寸固定,迭代次数可变

不可以

WTA-Diffusion

可以

可以

AD/SD

可以,聚合尺寸固定,迭代次数可变

不可以

WTA-membrane

可以

可以

AD/SD

可以,聚合尺寸固定,迭代次数可变

不可以

WTA-Bayesian

可以

可以

AD/SD

可以,聚合尺寸固定,迭代次数可变

不可以

WTA-LASW

可以

可以

AD/SD

可以,聚合尺寸可变,迭代次数1次

不可以

SO

可以

可以

AD/SD

不可以

不可以

DP

可以

可以

AD/SD

不可以

不可以

GC

可以

可以

AD/SD

不可以

不可以

SA

可以

可以

AD/SD

不可以

不可以

BPAccel

可以

可以

AD/SD

不可以

不可以

BPSync

可以

可以

AD/SD

不可以

不可以

1. 主线函数

1.0 ComputeCorrespondence

  1. void ComputeCorrespondence()
  2. {
  3. CShape sh = m_frame[frame_ref].input_image.Shape();
  4. //1.计算m_frame_xxx, m_disp_xxx, disp_step, disp_n, m_match_outside
  5. //只考虑disp_step==1的情况,所以可进行以下简化
  6. //且后文件将除m_disp_n外的所有m_frame_xxx和m_disp_xxx都去掉
  7. m_frame_diff = ;// frame_match - frame_ref;
  8. m_frame_diff_sign = ;// (m_frame_diff > 0) ? 1 : -1;
  9. m_disp_num = ;// disp_step < 1.0f ? 1 : ROUND(disp_step);
  10. m_disp_den = ;// disp_step < 1.0f ? ROUND(1.0 / disp_step) : 1;
  11. m_disp_step_inv = ;// m_disp_den / (float)m_disp_num;
  12. m_disp_step = disp_step;// m_disp_num / (float)m_disp_den;
  13. m_disp_n = disp_n = disp_max-disp_min + ;// int(m_disp_step_inv * (disp_max - disp_min)) + 1;
  14. //disp_step = m_disp_step;
  15. //disp_n = m_disp_n;
  16. // Special value for border matches
  17. * : );
  18. int cutoff = (match_fn == eSD) ? match_max * match_max : abs(match_max);
  19. m_match_outside = __min(worst_match, cutoff); // trim to cutoff
  20.  
  21. //2.设置左右图像
  22. m_reference.ReAllocate(sh);
  23. CopyPixels(m_frame[frame_ref].input_image, m_reference);
  24. m_matching.ReAllocate(sh);
  25. CopyPixels(m_frame[frame_match].input_image, m_matching);
  26.  
  27. //3.设置标准视差图像
  28. sh.nBands = ;
  29. m_true_disparity.ReAllocate(sh); // ground truth
  30. ScaleAndOffset(m_frame[frame_ref].truth_image, m_true_disparity, 1.0f / disp_scale, disp_min);
  31.  
  32. //4.生成浮点视差图像
  33. sh.nBands = ;
  34. m_float_disparity.ReAllocate(sh);
  35. m_float_disparity.ClearPixels();
  36.  
  37. //5.生成整型视差图像
  38. sh.nBands = ;
  39. m_disparity.ReAllocate(sh); // winning disparities
  40.  
  41. //6.生成代价函数图像
  42. sh.nBands = m_disp_n;// number of disparity levels
  43. m_cost.ReAllocate(sh); // raw matching costs (# bands = # disparities)
  44.  
  45. //if (evaluate_only){暂且略去}
  46. //7.执行算法
  47. clock_t time0 = clock();
  48. PreProcess(); // see StcPreProcess.cpp
  49. RawCosts(); // see StcRawCosts.cpp
  50. Aggregate(); // see StcAggregate.cpp
  51. Optimize(); // see StcOptimize.cpp
  52. Refine(); // see StcRefine.cpp
  53. clock_t time1 = clock(); // record end time
  54. total_time = (float)(time1 - time0) / (float)CLOCKS_PER_SEC;
  55.  
  56. //8.生成并设置深度图像
  57. sh.nBands = ;
  58. m_frame[frame_ref].depth_image.ReAllocate(sh);
  59. m_frame[frame_ref].depth_image.ClearPixels(); // set to 0 if we just reallocated
  60. ScaleAndOffset(m_float_disparity, m_frame[frame_ref].depth_image, disp_scale, -disp_min * disp_scale + 0.5);
  61.  
  62. //9.
  63. CopyPixels(m_frame[frame_ref].input_image, m_reference);
  64. }

1.1 PreProcess

  1. void PreProcess()
  2. {
  3. ; iter < preproc_blur_iter; iter++)
  4. {
  5. ConvolveSeparable(m_reference, m_reference, ConvolveKernel_121, ConvolveKernel_14641, , );
  6. ConvolveSeparable(m_matching, m_matching, ConvolveKernel_121, ConvolveKernel_14641, , );
  7. }
  8. //Currently, we only support iterated binomial blur, to clean up the images a little.
  9. //This should help sub-pixel fitting work better, by making image shifts closer to a Taylor series expansion,
  10. //but will result in worse performance near discontinuity regions and in finely textured regions.
  11. //Other potential pre-processing operations (currently not implemented),might include:
  12. //(1)bias and gain normalization
  13. //(2)histogram equalization (global or local)
  14. //(3)rank statistics pre-processing
  15. }

1.2 RawCosts

  1. void RawCosts()
  2. {
  3. CShape sh = m_reference.Shape();
  4. int cols = sh.width;
  5. int rows = sh.height;
  6. int cn = sh.nBands;
  7. fprintf(stderr, match_fn == eAD ? "\nmatch_fn=AD, match_max=%d\n" : (match_fn == eSD ? "\nmatch_fn=SD, match_max=%d\n" : "\nmatch_fn=unknown, match_max=%d\n"), match_max);
  8.  
  9. int cutoff = (match_fn == eSD) ? match_max * match_max : abs(match_max);
  10. ; d < disp_n; d++)
  11. {
  12. int disp = -(disp_min + d);//计算取不同视差值的代价(一个视差值对应一个cost的通道)
  13. ; i < rows; i++)
  14. {
  15. uchar *, i, );
  16. uchar *match = &m_matching.Pixel(, i, );
  17. , i, d);
  18. , jj = ; j < cols; j++, jj += disp_n)//m_cost的通道数为disp_n
  19. {
  20. //1.肯定为错误匹配则代价无穷大
  21. )
  22. {
  23. cost[jj] = m_match_outside;
  24. continue;
  25. }
  26.  
  27. //2.否则计算AD代价或SD代价
  28. ;//多通道则是所有通道代价之和
  29. uchar *pixel0 = &ref[j*cn];
  30. uchar *pixel1 = &match[(j + disp)*cn];
  31. ; k < cn; k++)
  32. {
  33. int diff1 = (int)pixel1[k] - (int)pixel0[k];
  34. int diff2 = (match_fn == eSD) ? diff1 * diff1 : abs(diff1);
  35. diff_sum = diff_sum + diff2;
  36. }
  37. cost[jj] = __min(diff_sum, cutoff);
  38. }
  39. }
  40. }
  41. }

1.2.1 PadCosts

  1. void PadCosts()
  2. { // fill the outside parts of the DSI
  3. CShape sh = m_cost.Shape();
  4. int cols = sh.width;
  5. int rows = sh.height;
  6.  
  7. ; d < m_disp_n; d++)
  8. {
  9. int disp = -(disp_min + d);
  10. ; i < rows; i++)
  11. {
  12. , i, d);
  13. , jj = ; j < cols; j++, jj += disp_n)//m_cost的通道数为disp_n
  14. cost[jj] = ((j + disp) < ) ? m_match_outside : cost[jj];
  15. }
  16. }
  17. }

1.3 Aggregate

  1. void Aggregate()
  2. {
  3. // Save the raw matching costs in m_cost0;
  4. CopyPixels(m_cost, m_cost0);
  5.  
  6. //1.Perform given number of iteration steps
  7. ; iter < aggr_iter; iter++)
  8. switch (aggr_fn)
  9. {
  10. case eBox:
  11. ) fprintf(stderr, ", box=%d", aggr_window_size);
  12. BoxFilter(m_cost, m_cost, aggr_window_size, aggr_window_size, true);//可以用cv::boxFilter()代替
  13. break;
  14.  
  15. case eASWeight:
  16. ) fprintf(stderr, ", AdaptiveWeight (box=%d gamma_p=%g gamma_s=%g color_space=%d )", aggr_window_size, aggr_gamma_proximity, aggr_gamma_similarity, aggr_color_space);
  17. LASW(m_cost, // initial matching cost
  18. m_cost, // aggregated matching cost
  19. m_reference, // reference image
  20. m_matching, // target image
  21. aggr_window_size, // window size - x
  22. aggr_window_size, // window size - y
  23. aggr_gamma_proximity, // gamma_p
  24. aggr_gamma_similarity, // gamma_c
  25. aggr_color_space, // color space
  26. aggr_iter // iteration number (aggregation)
  27. );
  28. iter = aggr_iter;
  29. break;
  30.  
  31. default:
  32. throw CError("CStereoMatcher::Aggregate(): unknown aggregation function");
  33. }
  34.  
  35. //2.Simulate the effect of shiftable windows
  36. ) MinFilter(m_cost, m_cost, aggr_minfilter, aggr_minfilter);
  37.  
  38. //3.Pad the outside costs back up to bad values
  39. PadCosts();
  40. }

1.3.1 MinFilter

  1. {
  2. //略
  3. }

1.4 Optimize

  1. void Optimize()
  2. {
  3. // Select the best matches using local or global optimization
  4.  
  5. // set up the smoothness cost function for the methods that need it
  6. if (opt_fn == eDynamicProg || opt_fn == eScanlineOpt || opt_fn == eGraphCut || opt_fn == eSimulAnnl || opt_fn == eBPAccel || opt_fn == eBPSync)
  7. {
  8. if (verbose == eVerboseSummary) fprintf(stderr, ", smooth=%g, grad_thres=%g, penalty=%g", opt_smoothness, opt_grad_thresh, opt_grad_penalty);
  9. SmoothCostAll();
  10. }
  11.  
  12. switch (opt_fn)
  13. {
  14. case eNoOpt: // no optimization (pass through input depth maps)
  15. if (verbose == eVerboseSummary) fprintf(stderr, ", NO OPT");
  16. break;
  17.  
  18. case eWTA: // winner-take-all (local minimum)
  19. if (verbose == eVerboseSummary) fprintf(stderr, ", WTA");
  20. OptWTA();
  21. break;
  22.  
  23. case eGraphCut: // graph-cut global minimization
  24. if (verbose == eVerboseSummary) fprintf(stderr, ", GC");
  25. OptWTA(); // get an initial labelling (or just set to 0???)
  26. OptGraphCut(); // run the optimization
  27. break;
  28.  
  29. case eDynamicProg: // scanline dynamic programming
  30. if (verbose == eVerboseSummary) fprintf(stderr, ", DP (occl_cost=%d)", opt_occlusion_cost);
  31. OptDP(); // see StcOptDP.cpp
  32. break;
  33.  
  34. case eScanlineOpt: // scanline optimization
  35. if (verbose == eVerboseSummary) fprintf(stderr, ", SO");
  36. OptSO(); // see StcOptSO.cpp
  37. break;
  38.  
  39. case eSimulAnnl: // simulated annealing
  40. if (verbose == eVerboseSummary) fprintf(stderr, ", SA");
  41. OptWTA(); // initialize to reasonable starting point (for low-T gradient descent)
  42. OptSimulAnnl(); // see StcSimulAnn.cpp
  43. break;
  44.  
  45. case eBPAccel:
  46. OptBP(); // run the optimization
  47. break;
  48.  
  49. case eBPSync:
  50. OptBPSync(); // run the optimization
  51. break;
  52.  
  53. default:
  54. throw CError("CStereoMatcher::Optimize(): unknown optimization function");
  55. }
  56.  
  57. if (final_energy < 0.0f)
  58. {
  59. if (!m_cost.Shape().SameIgnoringNBands(m_smooth.Shape()))
  60. SmoothCostAll();
  61. float finalEd, finalEn;
  62. CStereoMatcher::ComputeEnergy(finalEd, finalEn);
  63. final_energy = finalEd + finalEn;
  64. }
  65. }

1.4.1 SmoothCostOne

  1. float SmoothCostOne(uchar *pixel1, uchar *pixel2, int cn)
  2. {
  3. float tmp = 0.0;
  4. ; k < cn; k++)
  5. {
  6. float tm = int(pixel1[k]) - int(pixel2[k]);
  7. tmp += tm*tm;
  8. }
  9. tmp = tmp/(cn - (cn > ));//归一化为单通道, ppm图像的通道为4
  10. tmp = sqrt(tmp);
  11. return (tmp < opt_grad_thresh) ? (opt_smoothness*opt_grad_penalty) : opt_smoothness;
  12. }

1.4.2 SmoothCostAll

  1. void SmoothCostAll()
  2. { //calculate smoothness costs for DP and GC
  3. CShape sh = m_cost.m_shape;
  4. sh.nBands = ;//分为垂直和水平平滑代价
  5. m_smooth.ReAllocate(sh, false);
  6. int rows = sh.height;
  7. int cols = sh.width;
  8. int cn = m_reference.m_shape.nBands;
  9.  
  10. char *im_data0_cr = m_reference.m_memStart;
  11. char *im_data0_dw = im_data0_cr + m_reference.m_rowSize;
  12. char *smooth_data0 = m_smooth.m_memStart;
  13. ; i < rows; i++, im_data0_cr += m_reference.m_rowSize, im_data0_dw += m_reference.m_rowSize, smooth_data0 += m_smooth.m_rowSize)
  14. {
  15. uchar *im_data1_cr = (uchar*)im_data0_cr;
  16. uchar *im_data1_dw = (uchar*)((i < rows - ) ? im_data0_dw : im_data0_cr);
  17. float *smooth_data1 = (float*)smooth_data0;
  18. ; j < cols; j++, im_data1_cr += cn, im_data1_dw += cn, smooth_data1 += )
  19. {
  20. smooth_data1[] = (i < rows - ) ? SmoothCostOne(im_data1_cr, im_data1_dw, cn) : ;
  21. smooth_data1[] = (j < cols - ) ? SmoothCostOne(im_data1_cr, im_data1_cr + cn, cn) : ;
  22. }
  23. }
  24. }

1.4.3 ComputeEnergy

  1. static void ComputeEnergy(CFloatImage& m_cost, CFloatImage& m_smooth, CIntImage& m_disparity, float& dataEnergy, float& smoothEnergy)
  2. {
  3. int cols = m_cost.m_shape.width;
  4. int rows = m_cost.m_shape.height;
  5. int cn1 = m_cost.m_shape.nBands;
  6. int cn2 = m_smooth.m_shape.nBands;
  7.  
  8. float sum1 = 0.0f;
  9. float sum2 = 0.0f;
  10. char *disp_data0_cr = m_disparity.m_memStart;
  11. char *disp_data0_dw = disp_data0_cr + m_disparity.m_rowSize;
  12. char *datacost_data0 = m_cost.m_memStart;
  13. char *smoothcost_data0 = m_smooth.m_memStart;
  14. ; i < rows; i++, disp_data0_cr += m_disparity.m_rowSize, disp_data0_dw += m_disparity.m_rowSize, datacost_data0 += m_cost.m_rowSize, smoothcost_data0 += m_smooth.m_rowSize)
  15. {
  16. int *disp_data1_cr = (int*)disp_data0_cr;
  17. ) ? disp_data0_dw : disp_data0_cr);
  18. float *datacost_data1 = (float*)datacost_data0;
  19. float *smoothcost_data1 = (float*)smoothcost_data0;
  20. ; j < cols; j++, datacost_data1 += cn1, smoothcost_data1 += cn2)
  21. {
  22. int d = disp_data1_cr[j];
  23.  
  24. sum1 = sum1 + datacost_data1[d];
  25. sum2 = sum2 + ((i < rows - && d != disp_data1_dw[j]) ? smoothcost_data1[] : );//水平平滑代价
  26. sum2 = sum2 + ((j < cols - && d != disp_data1_cr[j + ]) ? smoothcost_data1[] : );//垂直平滑代价
  27. }
  28. }
  29. dataEnergy = sum1;
  30. smoothEnergy = sum2;
  31.  
  32. //float GC_scale = (1 << 30) / (256 * 256);
  33. //GC_scale = (1 << 30) / (sum1 + sum2);
  34. }

1.5 Refine

  1. void Refine()
  2. { //Refine the matching disparity to get a sub-pixel match
  3. if (opt_fn != eNoOpt) ScaleAndOffset(m_disparity, m_float_disparity, disp_step, disp_min);//无优化则跳过
  4. || disp_n < ) return; //不进行提纯
  5.  
  6. ; i < m_cost.m_shape.height; i++)
  7. {
  8. , i, );
  9. , i, );
  10. , i, );
  11.  
  12. ; j < m_cost.m_shape.width; j++, cost += disp_n)
  13. {
  14. //Get minimum, but offset by 1 from ends
  15. ) - (disp[j] == disp_n - );
  16.  
  17. //Compute the equations of the parabolic fit
  18. ]; //a*(d-1)^2+b*(d-1)+c=c0
  19. float c1 = cost[d_min]; //a*(d )^2+b*(d )+c=c1
  20. ]; //a*(d+1)^2+b*(d+1)+c=c2
  21. float a = 0.5 * (c0 - 2.0 * c1 + c2); //解得a=c2-2*c1+c0, 对称轴=-b/2*a=d-(c2-c0)/(4*a)
  22. float b = 0.5 * (c2 - c0);
  23. if (a <= 0.0 || a < 0.5 * fabs(b)) continue;
  24.  
  25. //Solve for minimum
  26. float x0 = -0.5 * b / a;
  27. float d_new = m_disp_step * (d_min + x0) + disp_min;
  28. fdisp[j] = d_new;
  29. }
  30. }
  31. }

2.代价聚合
2.1 BoxFiter

  1. {
  2. //与cv::boxFilter一致
  3. }

2.2 LASW

  1. void LASW(CFloatImage &srcCost, CFloatImage &dstCost, CByteImage &im0, CByteImage &im1, int xWidth, int yWidth, float proximity, float similarity, int color_space, int diff_iter)
  2. {
  3. int frm_total = im0.m_shape.width*im0.m_shape.height;
  4. int win_radius = (int)(xWidth / 2.0);
  5. int win_total = xWidth*yWidth;
  6.  
  7. //0.分配所需空间
  8. double **Lab0 = new double *[frm_total];
  9. double **Lab1 = new double *[frm_total];
  10. float **rawCostf = new float *[frm_total];
  11. float **dstCostf = new float *[frm_total];
  12. float **sw0f = new float *[frm_total];
  13. float **sw1f = new float *[frm_total];
  14. ; i < frm_total; i++)
  15. {
  16. Lab0[i] = ];
  17. Lab1[i] = ];
  18. rawCostf[i] = new float[srcCost.m_shape.nBands];
  19. dstCostf[i] = new float[srcCost.m_shape.nBands];
  20. sw0f[i] = new float[win_total];
  21. sw1f[i] = new float[win_total];
  22. }
  23.  
  24. //1.计算Lab图像并
  25. , index = ; i<im0.m_shape.height; i++)
  26. ; j<im0.m_shape.width; j++, index++)
  27. {
  28. double R, G, B;
  29. R = im0.Pixel(j, i, ((im0.m_shape.nBands - ) == ) ? : );
  30. G = im0.Pixel(j, i, ((im0.m_shape.nBands - ) == ) ? : );
  31. B = im0.Pixel(j, i, ((im0.m_shape.nBands - ) == ) ? : );
  32. RGB2Lab(R, G, B, Lab0[index][], Lab0[index][], Lab0[index][]);
  33. R = im1.Pixel(j, i, ((im1.m_shape.nBands - ) == ) ? : );
  34. G = im1.Pixel(j, i, ((im1.m_shape.nBands - ) == ) ? : );
  35. B = im1.Pixel(j, i, ((im1.m_shape.nBands - ) == ) ? : );
  36. RGB2Lab(R, G, B, Lab1[index][], Lab1[index][], Lab1[index][]);
  37. }
  38.  
  39. //2.取得原始代价
  40. , index = ; i<srcCost.m_shape.height; i++)
  41. ; j < srcCost.m_shape.width; j++, index++)
  42. ; k<srcCost.m_shape.nBands; k++)
  43. rawCostf[index][k] = (float)srcCost.Pixel(j, i, k);
  44.  
  45. //3.计算自适应权重
  46. calcASW(Lab0, sw0f, proximity, similarity, win_radius, im0.m_shape.width, im0.m_shape.height);
  47. calcASW(Lab1, sw1f, proximity, similarity, win_radius, im0.m_shape.width, im0.m_shape.height);
  48.  
  49. //4.求和自适应权重
  50. ; u<diff_iter; u++)
  51. {
  52. aggrASW(sw0f, sw1f, rawCostf, dstCostf, srcCost.m_shape.nBands, win_radius, im0.m_shape.width, im0.m_shape.height);
  53. ; k<frm_total; k++)
  54. memcpy(rawCostf[k], dstCostf[k], sizeof(float)*srcCost.m_shape.nBands);
  55. }
  56.  
  57. //5.返回结果
  58. , index = ; i<dstCost.m_shape.height; i++)
  59. ; j<dstCost.m_shape.width; j++, index++)
  60. ; k<dstCost.m_shape.nBands; k++)
  61. (())[k] = dstCostf[index][k];
  62.  
  63. //6.删除分配的空间
  64. ; i < frm_total; i++)
  65. {
  66. delete Lab0[i];
  67. delete Lab1[i];
  68. delete rawCostf[i];
  69. delete dstCostf[i];
  70. delete sw0f[i];
  71. delete sw1f[i];
  72. }
  73. }

2.2.1 RGB2Lab

  1. void RGB2Lab(double &R, double &G, double &B, double &L, double &a, double &b)
  2. {
  3. double X = 0.412453*R + 0.357580*G + 0.189423*B;
  4. double Y = 0.212671*R + 0.715160*G + 0.072169*B;
  5. double Z = 0.019334*R + 0.119193*G + 0.950227*B;
  6. double Xo = 244.66128;
  7. double Yo = 255.0;
  8. double Zo = 277.63227;
  9. double tm1 = X / Xo; tm1 = (tm1 > 0.008856) ? pow(tm1, 0.333333333) : (7.787*tm1 + 0.137931034);
  10. double tm2 = Y / Yo; tm2 = (tm2 > 0.008856) ? pow(tm2, 0.333333333) : (7.787*tm2 + 0.137931034);
  11. double tm3 = Z / Zo; tm3 = (tm3 > 0.008856) ? pow(tm3, 0.333333333) : (7.787*tm3 + 0.137931034);
  12. L = * tm2 - ;
  13. a = * (tm1 - tm2);
  14. b = * (tm2 - tm3);
  15. }

2.2.2 calcASW

  1. void calcASW(double **Lab, float **SW, double proximity, double similarity, int win_radius, int cols, int rows)
  2. {
  3. int frm_total = cols*rows;
  4. * win_radius + )*( * win_radius + );
  5.  
  6. //0.先清零
  7. ; i<frm_total; i++)
  8. memset(SW[i], , sizeof(float)*win_total);
  9.  
  10. //1.计算自适用权重
  11. , index = ; i<rows; i++) //计算index点的领域点(共win_total个)相对index点的自适应权重,
  12. ; j<cols; j++, index++) //每个自适应权重占用SW的一个通道,索引越小的通道对应越左上角的点
  13. ; y <= win_radius; y++)//依次从左到右从上到下计算领域点相对于index点的自适应权重, k表示第k个领域点
  14. {
  15. int ii = i + y;
  16. || ii >= rows)//此行领域点越界,所以对应的权重都为0
  17. {
  18. for (int x = -win_radius; x <= win_radius; x++, k++)
  19. SW[index][k] = ;//可用menset加快处理
  20. continue;
  21. }
  22. for (int x = -win_radius; x <= win_radius; x++, k++)
  23. {
  24. ) //之前的循环已经计算则无需再计算
  25. continue;
  26. int jj = j + x;
  27. || jj >= cols)//此领域点越界,所以对应的权重为0
  28. {
  29. SW[index][k] = ;
  30. continue;
  31. }
  32. ];
  33. ];
  34. ];
  35. int index1 = ii*cols + jj;//领域点坐标
  36. ];
  37. ];
  38. ];
  39. double weight_prox = exp(-sqrt((double)(y*y + x*x)) / proximity);
  40. double weight_simi = exp(-sqrt((L1 - L2)*(L1 - L2) + (a1 - a2)*(a1 - a2) + (b1 - b2)*(b1 - b2)) / similarity);
  41. SW[index][k] = (float)(weight_prox*weight_simi);
  42. SW[index1][win_total - - k] = SW[index][k];//得到A相对O权重的同时也得到O相对A权重
  43. }
  44. }
  45. }

2.2.3 aggrASW

  1. void aggrASW(float **SW0, float **SW1, float **rawCost, float **dstCost, int cn, int win_radius, int cols, int rows)
  2. {
  3. , index = ; i<rows; i++)
  4. ; j<cols; j++, index++)
  5. ; d<cn; d++)//处理第d个通道
  6. {
  7. int index1 = j - d;//右图像上匹配点的坐标
  8. ) index1 = index1 + cols;
  9. else if (index1 >= cols) index1 = index1 - cols;
  10. index1 = i*cols + index1;//右图像上匹配点的坐标
  11.  
  12. ;
  13. ;
  14. ; y <= win_radius; y++)//k表示第k个领域点
  15. {
  16. int ii = i + y;
  17. ) ii = ii + rows;
  18. if (ii >= rows) ii = ii - rows;
  19.  
  20. for (int x = -win_radius; x <= win_radius; x++, k++)
  21. {
  22. int jj = j + x;
  23. ) jj = cols + jj;
  24. else if (jj >= cols) jj = jj - cols;
  25.  
  26. double weight = SW0[index][k] * SW1[index1][k];//权重之积
  27. weight_sum = weight_sum + weight;
  28. int index_k = ii*cols + jj;//index_k表示第k个领域点
  29. cost_sum = cost_sum + rawCost[index_k][d] * weight;
  30. }
  31. }
  32. dstCost[index][d] = (float)(cost_sum / weight_sum);
  33. }
  34. }

3.视差优化
3.1 OptWTA

  1. void CStereoMatcher::OptWTA()
  2. {
  3. CShape sh = m_cost.Shape();
  4. int cols = sh.width;
  5. int rows = sh.height;
  6.  
  7. ; i < rows; i++)
  8. {
  9. , i, );
  10. , i, );
  11. ; j < cols; j++, cost += disp_n)//m_cost的通道数为disp_n
  12. {
  13. ;
  14. ];
  15. ; d < disp_n; d++)
  16. if (cost[d] < best_cost)
  17. {
  18. best_cost = cost[d];
  19. best_disp = d;
  20. }
  21. disp[j] = best_disp;
  22. }
  23. }
  24. }

3.2 OptSO

  1. void OptSO()
  2. { // scanline optimization
  3. int cols = m_cost.m_shape.width;
  4. int rows = m_cost.m_shape.height;
  5.  
  6. ;
  7. int rowElem = cols*disp_n;
  8. char *datacost_data0 = m_cost.m_memStart;
  9. char *smoothcost_data0 = m_smooth.m_memStart;
  10. char *disparity_data0 = m_disparity.m_memStart;
  11. float *sumcost_data0 = (float*)malloc(rowElem*sizeof(float));//存储每一列的每一视差(通道)的最优结果
  12. int *position_data0 = (int*)malloc(rowElem*sizeof(int));//存储每一列取得最优结果时对应的前一列哪个索引的视差(通道)
  13. ; i < rows; i++, datacost_data0 += m_cost.m_rowSize, smoothcost_data0 += m_smooth.m_rowSize, disparity_data0 += m_disparity.m_rowSize)//对每一行
  14. {
  15. float *datacost_data1 = (float*)datacost_data0;
  16. float *smoothcost_data1 = (float*)smoothcost_data0;
  17. int *position_data1 = position_data0;
  18. float *sumcost_data1 = sumcost_data0;
  19.  
  20. //1.初始化第一列
  21. ; d < disp_n; d++)
  22. {
  23. position_data1[d] = -;
  24. sumcost_data1[d] = datacost_data1[d];
  25. }
  26. datacost_data1 += disp_n; position_data1 += disp_n; sumcost_data1 += disp_n;//定位第二列
  27.  
  28. //2.用动态归划处理后续列
  29. ; j < cols; j++, datacost_data1 += disp_n, position_data1 += disp_n, sumcost_data1 += disp_n, smoothcost_data1 += )//对每一列
  30. {
  31. ; d1 < disp_n; d1++)//对每一通道(视差)
  32. {
  33. sumcost_data1[d1] = COST_MAX; //当前列当前通道的最小匹配代价
  34. position_data1[d1] = -; //最小匹配代价对应前一列的哪个通道(视差)
  35. ; d0 < disp_n; d0++)//对前一列的每一通道(视差)
  36. {
  37. float tm = datacost_data1[d1]; //当前列当前通道(视差)的原始代价
  38. tm = tm + sumcost_data1[d0 - disp_n];//前一列的每一通道(视差)的最小匹配代价
  39. tm = (d0 != d1) ? (tm + smoothcost_data1[]) : tm;//两通道(视差)间的平滑代价(第二通道才是水平方向的平滑代价)
  40. if (tm < sumcost_data1[d1])
  41. {
  42. sumcost_data1[d1] = tm;
  43. position_data1[d1] = d0;
  44. }
  45. }
  46. }
  47. }
  48.  
  49. //3.在尾列查看最优结果(指针来源与前面不相关)
  50. position_data1 -= disp_n;
  51. sumcost_data1 -= disp_n;
  52. float best_cost = COST_MAX;
  53. ;
  54. ; d < disp_n; d++)
  55. if (sumcost_data1[d] < best_cost)
  56. {
  57. best_cost = sumcost_data1[d];
  58. best_disp = d;
  59. }
  60.  
  61. //4.回溯(从尾列到首列)
  62. int *disparity_data1 = (int*)disparity_data0;
  63. ; x--, position_data1 -= disp_n)
  64. {
  65. disparity_data1[x] = best_disp;
  66. best_disp = position_data1[best_disp];
  67. }
  68. }
  69. free(sumcost_data0);
  70. free(position_data0);
  71. }

3.3 OptDP

  1. void OptDP()
  2. { //dynamic programming stereo (Intille and Bobick, no GCPs)
  3. float ocl = opt_occlusion_cost;
  4. float ocr = opt_occlusion_cost;
  5. ; // marker for occluded pixels (use 0 if you want to leave occluded pixels black)
  6. int cols = m_cost.m_shape.width;
  7. int rows = m_cost.m_shape.height;
  8.  
  9. ] = { , , , , , , };//前一点的状态
  10. ] = { , , , , , , };//当前点的状态
  11. ;//每点的基元数=通道数*状态数
  12. , up = ;
  13. ] = { left, left, diag, diag, up, up, left };//不同状态时最优的前一点的位置与当前点的跨度
  14. , dup = ;
  15. ] = { dleft, dleft, ddiag, ddiag, dup, dup, dleft };//不同状态时视差的跨度
  16. ] = { , , , , , , }; //视差为0时没有左下角的前一点
  17. ] = { , , , , , , }; //视差为max没有同列的上一点
  18.  
  19. int rowElem = cols * colElem;
  20. char *datacost_data0 = m_cost.m_memStart;
  21. char *smoothcost_data0 = m_smooth.m_memStart;
  22. ) * m_disparity.m_pixSize;//视差是从最后列开始计算的
  23. int *position_data0 = (int*)malloc(rowElem*sizeof(int));//存储每一列取得最优结果时对应的前一列哪个索引的视差(通道)
  24. float *sumcost_data0 = (float*)malloc(rowElem*sizeof(float));//存储每一列的每一视差(通道)的最优结果
  25. )*colElem;
  26. )*colElem;
  27. ; i < rows; i++, datacost_data0 += m_cost.m_rowSize, smoothcost_data0 += m_smooth.m_rowSize, disparity_data0 += m_disparity.m_rowSize)
  28. {
  29. float *datacost_data1 = (float*)datacost_data0;
  30. float *smoothcost_data1 = (float*)smoothcost_data0;
  31. int *position_data1 = (int*)position_data0;
  32. float *sumcost_data1 = (float*)sumcost_data0;
  33.  
  34. //1.初始化第一列(每列有disp_n个通道(视差)而每个视差又有3个状态)
  35. {
  36. float *datacost_data2 = datacost_data1;
  37. int *position_data2 = position_data1;
  38. float *sumcost_data2 = sumcost_data1;
  39. ; d < disp_n; d++, datacost_data2++, position_data2 += , sumcost_data2 += )
  40. { //强制第一个点是非遮挡的
  41. position_data2[] = ;
  42. position_data2[] = -;
  43. position_data2[] = -;
  44. sumcost_data2[] = datacost_data2[];
  45. sumcost_data2[] = COST_MAX;
  46. sumcost_data2[] = COST_MAX;
  47. }
  48. datacost_data1 += disp_n; position_data1 += colElem; sumcost_data1 += colElem;//定位到第二列
  49. }
  50.  
  51. //2.用动态归划处理后续列
  52. ; j < cols; j++, datacost_data1 += disp_n, smoothcost_data1 += , position_data1 += colElem, sumcost_data1 += colElem)//对每一列
  53. {
  54. ;//先定位到第二列的最后一个通道,因为要从最后个通道开始处理
  55. float *smoothcost_data2 = smoothcost_data1;//平滑代价只与列相关而与通道无关
  56. ;//先定位到第二列的最后一个通道,因为要从最后个通道开始处理
  57. ;//从最后个通道开始处理是因为m→R和r→R时处理当前通道时要用到下一通道的数据
  58. ; d1 >= ; d1--, datacost_data2--, position_data2 -= , sumcost_data2 -= ) //对每一通道(视差)
  59. {
  60. sumcost_data2[] = COST_MAX;//当前列当前通道第0状态的最小匹配代价
  61. sumcost_data2[] = COST_MAX;//当前列当前通道第1状态的最小匹配代价
  62. sumcost_data2[] = COST_MAX;//当前列当前通道第2状态的最小匹配代价
  63. position_data2[] = -; //第0状态最小匹配代价对应前一列的哪个通道(视差)
  64. position_data2[] = -; //第1状态最小匹配代价对应前一列的哪个通道(视差)
  65. position_data2[] = -; //第2状态最小匹配代价对应前一列的哪个通道(视差)
  66.  
  67. ; t < ; t++)
  68. {
  69. && border0[t]) || (d1 == disp_n - && border1[t])) continue;//前一点不存在
  70. int pre_state = state0[t];
  71. int cur_state = state1[t];
  72. int pre_pos = steps[t] + pre_state;
  73.  
  74. ? ocl : (cur_state == ? ocr : datacost_data2[]));//当前列当前通道(视差)的原始代价
  75. tm = tm + sumcost_data2[pre_pos];//前一列的每一通道(视差)的每一状态的最小匹配代价
  76. tm = (t == || t == ) ? (tm + smoothcost_data2[]) : tm;//平滑代价(从遮挡到匹配时)//第二通道才是水平方向的平滑代价
  77. if (tm < sumcost_data2[cur_state])
  78. {
  79. sumcost_data2[cur_state] = tm;
  80. position_data2[cur_state] = t;
  81. }
  82. }
  83. }
  84. }
  85.  
  86. //3.在尾列查看最优结果(指针来源与前面不相关)
  87. float best_cost = COST_MAX;
  88. ;
  89. ;//只考虑左右图像都可见的状态
  90. {
  91. float *sumcost_data2 = sumcost_data1_endcol;//因为在遍历通道所以用data2
  92. ; d < disp_n; d++, sumcost_data2 += )
  93. if (sumcost_data2[best_state] < best_cost)
  94. {
  95. best_cost = sumcost_data2[best_state];
  96. best_disp = d;
  97. }
  98. }
  99.  
  100. //4.回溯(从尾列到首列)(指针来源与前面不相关)
  101. position_data1 = position_data1_endlcol + best_disp * + best_state;//因为在遍历列所以用data1
  102. int *disparity_data1 = (int*)disparity_data0;
  103. while (position_data1 >= position_data0)
  104. {
  105. int pos = *position_data1;
  106. int current_state = state1[pos];
  107. int prev_state = state0[pos];
  108. *disparity_data1 = (current_state == ) ? best_disp : occ;
  109.  
  110. int stride = steps[pos] - current_state + prev_state;
  111. position_data1 += stride;
  112.  
  113. best_disp += disp_step[pos];
  114. )
  115. {
  116. best_disp += disp_n;
  117. disparity_data1--;
  118. }
  119. }
  120. }
  121. free(sumcost_data0);
  122. free(position_data0);
  123.  
  124. //填充遮挡点(可单独写成函数)
  125. )
  126. {
  127. char *disp_data0 = m_disparity.m_memStart;
  128. ; i < rows; i++, disp_data0 += m_disparity.m_rowSize)
  129. {
  130. int *disp_data1 = (int*)disp_data0;
  131.  
  132. //找到第一个非遮掩点
  133. int nonocc;
  134. ; j < cols; j++)
  135. if (disp_data1[j] != occ)
  136. {
  137. nonocc = disp_data1[j];
  138. break;
  139. }
  140.  
  141. //除最左边的遮挡点外用与之右相邻的非遮挡点填充外, 其余遮挡点都用与之左相邻的非遮挡点填充
  142. ; j < cols; j++)
  143. {
  144. int d = disp_data1[j];
  145. if (d == occ)
  146. disp_data1[j] = nonocc;
  147. else
  148. nonocc = d;
  149. }
  150. }
  151. }
  152. }

8.杂项函数
8.1 BirchfieldTomasiMinMax

  1. void BirchfieldTomasiMinMax(int* buffer, int* min, int* max, int cols, int cn)
  2. {
  3. int cur, pre, nex;
  4. //第一个值
  5. cur = buffer[];
  6. pre = (buffer[] + buffer[] + ) / ;
  7. nex = (buffer[] + buffer[] + ) / ;
  8. min[] = __min(cur, __min(pre, nex));
  9. max[] = __max(cur, __max(pre, nex));
  10. //中间的值
  11. ; i < cols - ; i++)
  12. {
  13. cur = buffer[i];
  14. pre = (buffer[i] + buffer[i - ] + ) / ;
  15. nex = (buffer[i] + buffer[i + ] + ) / ;
  16. min[i] = __min(cur, __min(pre, nex));
  17. max[i] = __max(cur, __max(pre, nex));
  18. }
  19. //最后个值
  20. cur = buffer[cols - ];
  21. pre = (buffer[cols - ] + buffer[cols - ] + ) / ;
  22. nex = (buffer[cols - ] + buffer[cols - ] + ) / ;
  23. min[cols - ] = __min(cur, __min(pre, nex));
  24. max[cols - ] = __max(cur, __max(pre, nex));
  25. }

9. Image.h添加

(1)将所有private及protected成员变成public

(2)添加如下代码:

  1. #include <opencv2/opencv.hpp>
  2. using namespace cv;//将所有权限改为public
  3.  
  4. template <class T> Mat ImgToMat(CImageOf<T> *src)
  5. {
  6. Mat dst;
  7. const char *depth = src->m_pTI->name();
  8.  
  9. )
  10. {
  11. dst = Mat(src->m_shape.height, src->m_shape.width, CV_8UC(src->m_shape.nBands));
  12. ; k < src->m_shape.nBands; k++)
  13. ; i < src->m_shape.height; i++)
  14. ; j < src->m_shape.width; j++)
  15. *((unsigned char*)(dst.data + i*dst.step + j*dst.elemSize() + k*dst.elemSize1())) = *((unsigned char*)(src->m_memStart + i*src->m_rowSize + j*src->m_pixSize + k*src->m_bandSize));
  16. }
  17. )
  18. {
  19. dst = Mat(src->m_shape.height, src->m_shape.width, CV_8SC(src->m_shape.nBands));
  20. ; k < src->m_shape.nBands; k++)
  21. ; i < src->m_shape.height; i++)
  22. ; j < src->m_shape.width; j++)
  23. *((char*)(dst.data + i*dst.step + j*dst.elemSize() + k*dst.elemSize1())) = *((char*)(src->m_memStart + i*src->m_rowSize + j*src->m_pixSize + k*src->m_bandSize));
  24. }
  25. )
  26. {
  27. dst = Mat(src->m_shape.height, src->m_shape.width, CV_16UC(src->m_shape.nBands));
  28. ; k < src->m_shape.nBands; k++)
  29. ; i < src->m_shape.height; i++)
  30. ; j < src->m_shape.width; j++)
  31. *((unsigned short*)(dst.data + i*dst.step + j*dst.elemSize() + k*dst.elemSize1())) = *((unsigned short*)(src->m_memStart + i*src->m_rowSize + j*src->m_pixSize + k*src->m_bandSize));
  32. }
  33. )
  34. {
  35. dst = Mat(src->m_shape.height, src->m_shape.width, CV_16SC(src->m_shape.nBands));
  36. ; k < src->m_shape.nBands; k++)
  37. ; i < src->m_shape.height; i++)
  38. ; j < src->m_shape.width; j++)
  39. *((short*)(dst.data + i*dst.step + j*dst.elemSize() + k*dst.elemSize1())) = *((short*)(src->m_memStart + i*src->m_rowSize + j*src->m_pixSize + k*src->m_bandSize));
  40. }
  41. )
  42. {
  43. dst = Mat(src->m_shape.height, src->m_shape.width, CV_32FC(src->m_shape.nBands));
  44. ; k < src->m_shape.nBands; k++)
  45. ; i < src->m_shape.height; i++)
  46. ; j < src->m_shape.width; j++)
  47. *((float*)(dst.data + i*dst.step + j*dst.elemSize() + k*dst.elemSize1())) = *((float*)(src->m_memStart + i*src->m_rowSize + j*src->m_pixSize + k*src->m_bandSize));
  48. }
  49. )
  50. {
  51. dst = Mat(src->m_shape.height, src->m_shape.width, CV_32SC(src->m_shape.nBands));
  52. ; k < src->m_shape.nBands; k++)
  53. ; i < src->m_shape.height; i++)
  54. ; j < src->m_shape.width; j++)
  55. *((int*)(dst.data + i*dst.step + j*dst.elemSize() + k*dst.elemSize1())) = *((int*)(src->m_memStart + i*src->m_rowSize + j*src->m_pixSize + k*src->m_bandSize));
  56. }
  57. )
  58. {
  59. dst = Mat(src->m_shape.height, src->m_shape.width, CV_64FC(src->m_shape.nBands));
  60. ; k < src->m_shape.nBands; k++)
  61. ; i < src->m_shape.height; i++)
  62. ; j < src->m_shape.width; j++)
  63. *((double*)(dst.data + i*dst.step + j*dst.elemSize() + k*dst.elemSize1())) = *((double*)(src->m_memStart + i*src->m_rowSize + j*src->m_pixSize + k*src->m_bandSize));
  64. }
  65. return dst;
  66. }
  67.  
  68. template <class T> CImageOf<T> MatToImg(Mat* src)
  69. {
  70. CImageOf<T> dst;
  71. CShape shape(src->cols, src->rows, src->channels());
  72. dst.ReAllocate(shape);
  73. const char *depth = dst.m_pTI->name();
  74.  
  75. )
  76. {
  77. ; k < dst.m_shape.nBands; k++)
  78. ; i < dst.m_shape.height; i++)
  79. ; j < dst.m_shape.width; j++)
  80. *((unsigned char*)(dst.m_memStart + i*dst.m_rowSize + j*dst.m_pixSize + k*dst.m_bandSize)) = *((unsigned char*)(src->data + i*src->step + j*src->elemSize() + k*src->elemSize1()));
  81. }
  82. )
  83. {
  84. ; k < dst.m_shape.nBands; k++)
  85. ; i < dst.m_shape.height; i++)
  86. ; j < dst.m_shape.width; j++)
  87. *((char*)(dst.m_memStart + i*dst.m_rowSize + j*dst.m_pixSize + k*dst.m_bandSize)) = *((char*)(src->data + i*src->step + j*src->elemSize() + k*src->elemSize1()));
  88. }
  89. )
  90. {
  91. ; k < dst.m_shape.nBands; k++)
  92. ; i < dst.m_shape.height; i++)
  93. ; j < dst.m_shape.width; j++)
  94. *((unsigned short*)(dst.m_memStart + i*dst.m_rowSize + j*dst.m_pixSize + k*dst.m_bandSize)) = *((unsigned short*)(src->data + i*src->step + j*src->elemSize() + k*src->elemSize1()));
  95. }
  96. )
  97. {
  98. ; k < dst.m_shape.nBands; k++)
  99. ; i < dst.m_shape.height; i++)
  100. ; j < dst.m_shape.width; j++)
  101. *((short*)(dst.m_memStart + i*dst.m_rowSize + j*dst.m_pixSize + k*dst.m_bandSize)) = *((short*)(src->data + i*src->step + j*src->elemSize() + k*src->elemSize1()));
  102. }
  103. )
  104. {
  105. ; k < dst.m_shape.nBands; k++)
  106. ; i < dst.m_shape.height; i++)
  107. ; j < dst.m_shape.width; j++)
  108. *((float*)(dst.m_memStart + i*dst.m_rowSize + j*dst.m_pixSize + k*dst.m_bandSize)) = *((float*)(src->data + i*src->step + j*src->elemSize() + k*src->elemSize1()));
  109. }
  110. )
  111. {
  112. ; k < dst.m_shape.nBands; k++)
  113. ; i < dst.m_shape.height; i++)
  114. ; j < dst.m_shape.width; j++)
  115. *((int*)(dst.m_memStart + i*dst.m_rowSize + j*dst.m_pixSize + k*dst.m_bandSize)) = *((int*)(src->data + i*src->step + j*src->elemSize() + k*src->elemSize1()));
  116. }
  117. )
  118. {
  119. ; k < dst.m_shape.nBands; k++)
  120. ; i < dst.m_shape.height; i++)
  121. ; j < dst.m_shape.width; j++)
  122. *((double*)(dst.m_memStart + i*dst.m_rowSize + j*dst.m_pixSize + k*dst.m_bandSize)) = *((double*)(src->data + i*src->step + j*src->elemSize() + k*src->elemSize1()));
  123. }
  124. return dst;
  125. }
  126.  
  127. template <class T> void saveXML(string name, CImageOf<T>* src)
  128. {
  129. Mat dst = ImgToMat<T>(src);
  130. FileStorage fs;
  131. fs.open("./../TestData/" + name, FileStorage::WRITE);
  132. fs << "mat" << dst;
  133. fs.release();
  134. }
  135.  
  136. template <class T> void saveXML(string name, CImageOf<T>* src, int count)
  137. {
  138. vector<Mat> dst;
  139. ; i<count; i++)
  140. dst.push_back(ImgToMat<T>(&src[i]));
  141. FileStorage fs;
  142. fs.open("./../TestData/" + name, FileStorage::WRITE);
  143. fs << "vectorMat" << dst;
  144. fs.release();
  145. }

立体匹配:关于理解middlebury提供的立体匹配代码后的精减的更多相关文章

  1. 立体匹配:关于Middlebury提供的源码的简化使用

    Middlebury提供的源码,虽然花了不到一个小时就运行起来啦.但说实话,它那循环读取脚本命令来执行算法真是让我费了不少头脑,花了近三天时间,我才弄明白了它的运行机制.你说,我就想提取一下算法,你给 ...

  2. 立体匹配:关于Middlebury提供的源码的简化后的结构

  3. 深入理解Object提供的阻塞和唤醒API

    深入理解Object提供的阻塞和唤醒API 前提 前段时间花了大量时间去研读JUC中同步器AbstractQueuedSynchronizer的源码实现,再结合很久之前看过的一篇关于Object提供的 ...

  4. 通过Webstorm上传代码到Github、更新代码后同步到github及克隆github代码到本地的方法

    导读: Github做为IT爱好者分享代码的一个知名的平台,广受大家喜欢,那么我们平时该怎么将自己写的代码上传到github上面保存并且提供给其他人参考? 我想方法不外乎如下几个: 1.直接在gith ...

  5. Gitlab利用Webhook实现Push代码后的jenkins自动构建

    之前部署了Gitlab的代码托管平台和Jenkins的代码发布平台.通常是开发后的代码先推到Gitlab上管理,然后在Jenkins里通过脚本构建代码发布.这种方式每次在发版的时候,需要人工去执行je ...

  6. Git克隆代码后更新代码上传至服务器

    首先在本地新建一个文件夹,鼠标右键点击Git clone(熟悉命令的可以直接在Git Bsah Here 里输入命令进行克隆), 点击后在弹框中输入服务器url后点击ok               ...

  7. Gitlab使用Webhook实现Push代码后的jenkins自动构建

    本文出自https://www.cnblogs.com/kevingrace/p/6479813.html 怕以后找不到,所以先写到自己博客中 Gitlab利用Webhook实现Push代码后的jen ...

  8. Eclipse中避免修改后台代码后手动install和重启

      之前每次修改maven多模块项目后都得重新执行mvn install ,install完还得重启jetty/tomcat服务器,非常浪费   时间,其实修改代码后可以不用执行install,也不用 ...

  9. 更改html代码后网页不更新

    写了一个非常简单的 html 页面,只有简单的跳转功能,但是在 Eclipse 下更改代码后用 chrome 浏览器打开时还是显示原来的网页.开始我以为是网页有错误或者有不规范的地方,因为我编写的是 ...

随机推荐

  1. wikioi 1075 明明的随机数

    /*============================================================ 1075 明明的随机数 题目描述 Description 明明想在学校中请 ...

  2. 【转】jQuery选择器总结

    jQuery 的选择器可谓之强大无比,这里简单地总结一下常用的元素查找方法   $("#myELement")    选择id值等于myElement的元素,id值不能重复在文档中 ...

  3. C# toString()转换详细(转)

    文章转自:http://blog.csdn.net/xiaoguang44/article/details/6988418 字符型转换为字符串 // C 货币 2.5.ToString("C ...

  4. 制作OS X 10.10.3启动安装U盘

    http://www.cnblogs.com/Bob-wei/p/4471407.html 1.获得“Install OS X Yosemite.app” 2.准备一个8GB的U盘,用磁盘工具“抹掉” ...

  5. Jquery ajax提交表单几种方法详解

    [导读] 在jquery中ajax提交表单有post与get方式,在使用get方式时我们可以直接使用ajax 序列化表单$( 表单ID) serialize();就行了,下面我来介绍两个提交表单数据的 ...

  6. Struts2 - Interceptor中取得ActionName、Namespace、Method

    在Struts2的Interceptor中取得当前执行对应的ActionName.Namespace.Method方法: 可以使用: System.out.println(invocation.get ...

  7. bzoj1173: [Balkan2007]Point

    Description 给出N个三维空间上的点. 问有多少条直线,这些直线上至少有三个点. Input 第一行给出数字N,N在[4,1000] 下面N行,每行三个数字,用于描述点的坐标,其值在[-10 ...

  8. cgic 写CGI程序

    CGIC是C语言CGI库函数,用于编写CGI程序 CGIC 主要完成以下功能: * 对数据进行语法分析 * 接收以 GET 和 PSOT 两种方式发送的数据 * 把 FORM 中的不同域连接成连续的串 ...

  9. CXF发布restful WebService的入门例子(服务器端)

    研究了两天CXF对restful的支持.   现在,想实现一个以 http://localhost:9999/roomservice 为入口, http://localhost:9999/roomse ...

  10. 一. Logback与p6spy

    一. LogBack配置 配置pom.xml <dependency> <groupId>org.slf4j</groupId> <artifactId> ...