1. 什么是相位展开?

相位展开(Phase Unwrapping)是一个经典的信号处理问题,它指的是从值区间中恢复原始相位值(原因在于:计算相位时,运用反正切函数,则相位图中提取的相位都是包裹在一个周期相位区间的包裹相位值,并不是真实得到的相位)。二维相位展开问题广泛存在于诸如光学测量技术(数字全息干涉和条纹投影轮廓术、合成孔径雷达(SAR)[2]和磁共振成像(MRI)[3]...)等许多应用中。从这些应用中估算出的相位与考虑到的物体形状、地形高程和磁场不均匀性等物理参数有关。

理想情况下,相位展开可以通过在每个像素上根据相邻像素之间的相位差加减来实现(最简单的二维相位展开就是将这个二维展开的问题划为两个一位相位展开,即首先在行方向或者列方向进行一维相位展开,然后将得到的一列值或者一行值在另一个方向进行一维相位展开,得到展开好的二维图像)。然而,在实际应用中,相位展开是一个非常具有挑战性的问题,因为存在噪声严重、相位突变和相位不连续等情况。

2.相位展开应用场景(以光学三维测量为例)

(具体原理图省略...),

原文算法是用C编写,MATLAB调用的算法:

  1. //This program is written by Munther Gdeisat etc. to program the two-dimensional unwrapper
  2. //entitled "Fast two-dimensional phase-unwrapping algorithm based on sorting by
  3. //reliability following a noncontinuous path"
  4. //by M. A. Herraez, D. R. Burton, M. J. Lalor, and M. A. Gdeisat
  5. //published in the Applied Optics, Vol. 41, No. 35, pp. 7437, 2002.
  6. //This program is written on 15th August 2007
  7. //The wrapped phase map is floating point data type. Also, the unwrapped phase map is foloating point
  8. #include <malloc.h>
  9. #include<stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include "mex.h" //--This one is required
  13.  
  14. static float PI = 3.141592654;
  15. static float TWOPI = 6.283185307;
  16.  
  17. //pixel information
  18. struct PIXEL
  19. {
  20. //int x; //x coordinate of the pixel
  21. //int y; //y coordinate
  22. int increment; //No. of 2*pi to add to the pixel to unwrap it
  23. int number_of_pixels_in_group; //No. of pixels in the pixel group
  24. float value; //value of the pixel
  25. float reliability;
  26. int group; //group No.
  27. int new_group;
  28. struct PIXEL *head; //pointer to the first pixel in the group in the linked list
  29. struct PIXEL *last; //pointer to the last pixel in the group
  30. struct PIXEL *next; //pointer to the next pixel in the group
  31. };
  32.  
  33. //the EDGE is the line that connects two pixels.
  34. //if we have S PIXELs, then we have S horizental edges and S vertical edges
  35. struct EDGE
  36. {
  37. float reliab; //reliabilty of the edge and it depends on the two pixels
  38. PIXEL *pointer_1; //pointer to the first pixel
  39. PIXEL *pointer_2; //pointer to the second pixel
  40. int increment; //No. of 2*pi to add to one of the pixels to unwrap it with respect to the second
  41. };
  42.  
  43. //another version of Mixtogether but this function should only be use with the sort program
  44. void Mix(EDGE *Pointer1, int *index1, int *index2, int size)
  45. {
  46. int counter1 = 0;
  47. int counter2 = 0;
  48. int *TemporalPointer = index1;
  49.  
  50. int *Result = (int *)calloc(size * 2, sizeof(int));
  51. int *Follower = Result;
  52.  
  53. while ((counter1 < size) && (counter2 < size))
  54. {
  55. if ((Pointer1[*(index1 + counter1)].reliab <= Pointer1[*(index2 + counter2)].reliab))
  56. {
  57. *Follower = *(index1 + counter1);
  58. Follower++;
  59. counter1++;
  60. }
  61. else
  62. {
  63. *Follower = *(index2 + counter2);
  64. Follower++;
  65. counter2++;
  66. }
  67. }//while
  68.  
  69. if (counter1 == size)
  70. {
  71. memcpy(Follower, (index2 + counter2), sizeof(int)*(size - counter2));
  72. }
  73. else
  74. {
  75. memcpy(Follower, (index1 + counter1), sizeof(int)*(size - counter1));
  76. }
  77.  
  78. Follower = Result;
  79. index1 = TemporalPointer;
  80.  
  81. int i;
  82. for (i = 0; i < 2 * size; i++)
  83. {
  84. *index1 = *Follower;
  85. index1++;
  86. Follower++;
  87. }
  88.  
  89. free(Result);
  90. }
  91.  
  92. //this is may be the fastest sort program;
  93. //see the explination in quickSort function below
  94. void sort(EDGE *Pointer, int *index, int size)
  95. {
  96. if (size == 2)
  97. {
  98. if ((Pointer[*index].reliab) > (Pointer[*(index + 1)].reliab))
  99. {
  100. int Temp;
  101. Temp = *index;
  102. *index = *(index + 1);
  103. *(index + 1) = Temp;
  104. }
  105. }
  106. else if (size > 2)
  107. {
  108. sort(Pointer, index, size / 2);
  109. sort(Pointer, (index + (size / 2)), size / 2);
  110. Mix(Pointer, index, (index + (size / 2)), size / 2);
  111. }
  112. }
  113.  
  114. //this function tries to implement a nice idea explained below
  115. //we need to sort edge array. Each edge element conisists of 16 bytes.
  116. //In normal sort program we compare two elements in the array and exchange
  117. //their place under some conditions to do the sorting. It is very probable
  118. // that an edge element may change its place hundred of times which makes
  119. //the sorting a very time consuming operation. The idea in this function
  120. //is to give each edge element an index and move the index not the edge
  121. //element. The edge need 4 bytes which makes the sorting operation faster.
  122. // After finishingthe sorting of the indexes, we know the position of each index.
  123. //So we know how to sort edges
  124. void quick_sort(EDGE *Pointer, int size)
  125. {
  126. int *index = (int *)calloc(size, sizeof(int));
  127. int i;
  128.  
  129. for (i = 0; i < size; ++i)
  130. index[i] = i;
  131.  
  132. sort(Pointer, index, size);
  133.  
  134. EDGE * a = (EDGE *)calloc(size, sizeof(EDGE));
  135. for (i = 0; i < size; ++i)
  136. a[i] = Pointer[*(index + i)];
  137.  
  138. memcpy(Pointer, a, size * sizeof(EDGE));
  139.  
  140. free(index);
  141. free(a);
  142. }
  143.  
  144. void read_data(char *inputfile, float *Data, int length)
  145. {
  146. printf("Reading the Wrapped Values form Binary File.............>");
  147. FILE *ifptr;
  148. ifptr = fopen(inputfile, "rb");
  149. if (ifptr == NULL) printf("Error opening the file\n");
  150. fread(Data, sizeof(float), length, ifptr);
  151. fclose(ifptr);
  152. printf(" Done.\n");
  153. }
  154.  
  155. void write_data(char *outputfile, float *Data, int length)
  156. {
  157. printf("Writing the Unwrapped Values to Binary File.............>");
  158. FILE *ifptr;
  159. ifptr = fopen(outputfile, "wb");
  160. if (ifptr == NULL) printf("Error opening the file\n");
  161. fwrite(Data, sizeof(float), length, ifptr);
  162. fclose(ifptr);
  163. printf(" Done.\n");
  164. }
  165.  
  166. //---------------start quicker_sort algorithm --------------------------------
  167. #define swap(x,y) {EDGE t; t=x; x=y; y=t;}
  168. #define order(x,y) if (x.reliab > y.reliab) swap(x,y)
  169. #define o2(x,y) order(x,y)
  170. #define o3(x,y,z) o2(x,y); o2(x,z); o2(y,z)
  171.  
  172. typedef enum { yes, no } yes_no;
  173.  
  174. yes_no find_pivot(EDGE *left, EDGE *right, float *pivot_ptr)
  175. {
  176. EDGE a, b, c, *p;
  177.  
  178. a = *left;
  179. b = *(left + (right - left) / 2);
  180. c = *right;
  181. o3(a, b, c);
  182.  
  183. if (a.reliab < b.reliab)
  184. {
  185. *pivot_ptr = b.reliab;
  186. return yes;
  187. }
  188.  
  189. if (b.reliab < c.reliab)
  190. {
  191. *pivot_ptr = c.reliab;
  192. return yes;
  193. }
  194.  
  195. for (p = left + 1; p <= right; ++p)
  196. {
  197. if (p->reliab != left->reliab)
  198. {
  199. *pivot_ptr = (p->reliab < left->reliab) ? left->reliab : p->reliab;
  200. return yes;
  201. }
  202. return no;
  203. }
  204. }
  205.  
  206. EDGE *partition(EDGE *left, EDGE *right, float pivot)
  207. {
  208. while (left <= right)
  209. {
  210. while (left->reliab < pivot)
  211. ++left;
  212. while (right->reliab >= pivot)
  213. --right;
  214. if (left < right)
  215. {
  216. swap(*left, *right);
  217. ++left;
  218. --right;
  219. }
  220. }
  221. return left;
  222. }
  223.  
  224. void quicker_sort(EDGE *left, EDGE *right)
  225. {
  226. EDGE *p;
  227. float pivot;
  228.  
  229. if (find_pivot(left, right, &pivot) == yes)
  230. {
  231. p = partition(left, right, pivot);
  232. quicker_sort(left, p - 1);
  233. quicker_sort(p, right);
  234. }
  235. }
  236.  
  237. //--------------end quicker_sort algorithm -----------------------------------
  238.  
  239. //--------------------start initialse pixels ----------------------------------
  240. //initialse pixels. See the explination of the pixel class above.
  241. //initially every pixel is a gorup by its self
  242. void initialisePIXELs(float *WrappedImage, PIXEL *pixel, int image_width, int image_height)
  243. {
  244. PIXEL *pixel_pointer = pixel;
  245. float *wrapped_image_pointer = WrappedImage;
  246. int i, j;
  247.  
  248. for (i = 0; i < image_height; i++)
  249. {
  250. for (j = 0; j < image_width; j++)
  251. {
  252. //pixel_pointer->x = j;
  253. //pixel_pointer->y = i;
  254. pixel_pointer->increment = 0;
  255. pixel_pointer->number_of_pixels_in_group = 1;
  256. pixel_pointer->value = *wrapped_image_pointer;
  257. pixel_pointer->reliability = 9999999 + rand();
  258. pixel_pointer->head = pixel_pointer;
  259. pixel_pointer->last = pixel_pointer;
  260. pixel_pointer->next = NULL;
  261. pixel_pointer->new_group = 0;
  262. pixel_pointer->group = -1;
  263. pixel_pointer++;
  264. wrapped_image_pointer++;
  265. }
  266. }
  267. }
  268. //-------------------end initialise pixels -----------
  269.  
  270. //gamma function in the paper
  271. float wrap(float pixel_value)
  272. {
  273. float wrapped_pixel_value;
  274. if (pixel_value > PI) wrapped_pixel_value = pixel_value - TWOPI;
  275. else if (pixel_value < -PI) wrapped_pixel_value = pixel_value + TWOPI;
  276. else wrapped_pixel_value = pixel_value;
  277. return wrapped_pixel_value;
  278. }
  279.  
  280. // pixelL_value is the left pixel, pixelR_value is the right pixel
  281. int find_wrap(float pixelL_value, float pixelR_value)
  282. {
  283. float difference;
  284. int wrap_value;
  285. difference = pixelL_value - pixelR_value;
  286.  
  287. if (difference > PI) wrap_value = -1;
  288. else if (difference < -PI) wrap_value = 1;
  289. else wrap_value = 0;
  290.  
  291. return wrap_value;
  292. }
  293.  
  294. void calculate_reliability(float *wrappedImage, PIXEL *pixel, int image_width, int image_height)
  295. {
  296. int image_width_plus_one = image_width + 1;
  297. int image_width_minus_one = image_width - 1;
  298. PIXEL *pixel_pointer = pixel + image_width_plus_one;
  299. float *WIP = wrappedImage + image_width_plus_one; //WIP is the wrapped image pointer
  300. float H, V, D1, D2;
  301. int i, j;
  302.  
  303. for (i = 1; i < image_height - 1; ++i)
  304. {
  305. for (j = 1; j < image_width - 1; ++j)
  306. {
  307. H = wrap(*(WIP - 1) - *WIP) - wrap(*WIP - *(WIP + 1));
  308. V = wrap(*(WIP - image_width) - *WIP) - wrap(*WIP - *(WIP + image_width));
  309. D1 = wrap(*(WIP - image_width_plus_one) - *WIP) - wrap(*WIP - *(WIP + image_width_plus_one));
  310. D2 = wrap(*(WIP - image_width_minus_one) - *WIP) - wrap(*WIP - *(WIP + image_width_minus_one));
  311. pixel_pointer->reliability = H * H + V * V + D1 * D1 + D2 * D2;
  312. pixel_pointer++;
  313. WIP++;
  314. }
  315. pixel_pointer += 2;
  316. WIP += 2;
  317. }
  318. }
  319.  
  320. //calculate the reliability of the horizental edges of the image
  321. //it is calculated by adding the reliability of pixel and the relibility of
  322. //its right neighbour
  323. //edge is calculated between a pixel and its next neighbour
  324. void horizentalEDGEs(PIXEL *pixel, EDGE *edge, int image_width, int image_height)
  325. {
  326. int i, j;
  327. EDGE *edge_pointer = edge;
  328. PIXEL *pixel_pointer = pixel;
  329.  
  330. for (i = 0; i < image_height; i++)
  331. {
  332. for (j = 0; j < image_width - 1; j++)
  333. {
  334. edge_pointer->pointer_1 = pixel_pointer;
  335. edge_pointer->pointer_2 = (pixel_pointer + 1);
  336. edge_pointer->reliab = pixel_pointer->reliability + (pixel_pointer + 1)->reliability;
  337. edge_pointer->increment = find_wrap(pixel_pointer->value, (pixel_pointer + 1)->value);
  338. pixel_pointer++;
  339. edge_pointer++;
  340. }
  341. pixel_pointer++;
  342. }
  343. }
  344.  
  345. //calculate the reliability of the vertical EDGEs of the image
  346. //it is calculated by adding the reliability of pixel and the relibility of
  347. //its lower neighbour in the image.
  348. void verticalEDGEs(PIXEL *pixel, EDGE *edge, int image_width, int image_height)
  349. {
  350. int i, j;
  351.  
  352. PIXEL *pixel_pointer = pixel;
  353. EDGE *edge_pointer = edge + (image_height) * (image_width - 1);
  354.  
  355. for (i = 0; i < image_height - 1; i++)
  356. {
  357. for (j = 0; j < image_width; j++)
  358. {
  359. edge_pointer->pointer_1 = pixel_pointer;
  360. edge_pointer->pointer_2 = (pixel_pointer + image_width);
  361. edge_pointer->reliab = pixel_pointer->reliability + (pixel_pointer + image_width)->reliability;
  362. edge_pointer->increment = find_wrap(pixel_pointer->value, (pixel_pointer + image_width)->value);
  363. pixel_pointer++;
  364. edge_pointer++;
  365. } //j loop
  366. } // i loop
  367. }
  368.  
  369. //gather the pixels of the image into groups
  370. void gatherPIXELs(EDGE *edge, int image_width, int image_height)
  371. {
  372. int k;
  373.  
  374. //Number of rialiable edges (not at the borders of the image)
  375. int no_EDGEs = (image_width - 1) * (image_height)+(image_width) * (image_height - 1);
  376. PIXEL *PIXEL1;
  377. PIXEL *PIXEL2;
  378.  
  379. PIXEL *group1;
  380. PIXEL *group2;
  381. EDGE *pointer_edge = edge;
  382. int incremento;
  383.  
  384. for (k = 0; k < no_EDGEs; k++)
  385. {
  386. PIXEL1 = pointer_edge->pointer_1;
  387. PIXEL2 = pointer_edge->pointer_2;
  388.  
  389. //PIXEL 1 and PIXEL 2 belong to different groups
  390. //initially each pixel is a group by it self and one pixel can construct a group
  391. //no else or else if to this if
  392. if (PIXEL2->head != PIXEL1->head)
  393. {
  394. //PIXEL 2 is alone in its group
  395. //merge this pixel with PIXEL 1 group and find the number of 2 pi to add
  396. //to or subtract to unwrap it
  397. if ((PIXEL2->next == NULL) && (PIXEL2->head == PIXEL2))
  398. {
  399. PIXEL1->head->last->next = PIXEL2;
  400. PIXEL1->head->last = PIXEL2;
  401. (PIXEL1->head->number_of_pixels_in_group)++;
  402. PIXEL2->head = PIXEL1->head;
  403. PIXEL2->increment = PIXEL1->increment - pointer_edge->increment;
  404. }
  405.  
  406. //PIXEL 1 is alone in its group
  407. //merge this pixel with PIXEL 2 group and find the number of 2 pi to add
  408. //to or subtract to unwrap it
  409. else if ((PIXEL1->next == NULL) && (PIXEL1->head == PIXEL1))
  410. {
  411. PIXEL2->head->last->next = PIXEL1;
  412. PIXEL2->head->last = PIXEL1;
  413. (PIXEL2->head->number_of_pixels_in_group)++;
  414. PIXEL1->head = PIXEL2->head;
  415. PIXEL1->increment = PIXEL2->increment + pointer_edge->increment;
  416. }
  417.  
  418. //PIXEL 1 and PIXEL 2 both have groups
  419. else
  420. {
  421. group1 = PIXEL1->head;
  422. group2 = PIXEL2->head;
  423. //the no. of pixels in PIXEL 1 group is large than the no. of PIXELs
  424. //in PIXEL 2 group. Merge PIXEL 2 group to PIXEL 1 group
  425. //and find the number of wraps between PIXEL 2 group and PIXEL 1 group
  426. //to unwrap PIXEL 2 group with respect to PIXEL 1 group.
  427. //the no. of wraps will be added to PIXEL 2 grop in the future
  428. if (group1->number_of_pixels_in_group > group2->number_of_pixels_in_group)
  429. {
  430. //merge PIXEL 2 with PIXEL 1 group
  431. group1->last->next = group2;
  432. group1->last = group2->last;
  433. group1->number_of_pixels_in_group = group1->number_of_pixels_in_group + group2->number_of_pixels_in_group;
  434. incremento = PIXEL1->increment - pointer_edge->increment - PIXEL2->increment;
  435. //merge the other pixels in PIXEL 2 group to PIXEL 1 group
  436. while (group2 != NULL)
  437. {
  438. group2->head = group1;
  439. group2->increment += incremento;
  440. group2 = group2->next;
  441. }
  442. }
  443.  
  444. //the no. of PIXELs in PIXEL 2 group is large than the no. of PIXELs
  445. //in PIXEL 1 group. Merge PIXEL 1 group to PIXEL 2 group
  446. //and find the number of wraps between PIXEL 2 group and PIXEL 1 group
  447. //to unwrap PIXEL 1 group with respect to PIXEL 2 group.
  448. //the no. of wraps will be added to PIXEL 1 grop in the future
  449. else
  450. {
  451. //merge PIXEL 1 with PIXEL 2 group
  452. group2->last->next = group1;
  453. group2->last = group1->last;
  454. group2->number_of_pixels_in_group = group2->number_of_pixels_in_group + group1->number_of_pixels_in_group;
  455. incremento = PIXEL2->increment + pointer_edge->increment - PIXEL1->increment;
  456. //merge the other pixels in PIXEL 2 group to PIXEL 1 group
  457. while (group1 != NULL)
  458. {
  459. group1->head = group2;
  460. group1->increment += incremento;
  461. group1 = group1->next;
  462. } // while
  463.  
  464. } // else
  465. } //else
  466. };//if
  467.  
  468. pointer_edge++;
  469. }
  470. }
  471.  
  472. //unwrap the image
  473. void unwrapImage(PIXEL *pixel, int image_width, int image_height)
  474. {
  475. int i;
  476. int image_size = image_width * image_height;
  477. PIXEL *pixel_pointer = pixel;
  478.  
  479. for (i = 0; i < image_size; i++)
  480. {
  481. pixel_pointer->value += TWOPI * (float)(pixel_pointer->increment);
  482. pixel_pointer++;
  483. }
  484. }
  485.  
  486. //the input to this unwrapper is an array that contains the wrapped phase map.
  487. //copy the image on the buffer passed to this unwrapper to over write the unwrapped
  488. //phase map on the buffer of the wrapped phase map.
  489. void returnImage(PIXEL *pixel, float *unwrappedImage, int image_width, int image_height)
  490. {
  491. int i;
  492. int image_size = image_width * image_height;
  493. float *unwrappedImage_pointer = unwrappedImage;
  494. PIXEL *pixel_pointer = pixel;
  495.  
  496. for (i = 0; i < image_size; i++)
  497. {
  498. *unwrappedImage_pointer = pixel_pointer->value;
  499. pixel_pointer++;
  500. unwrappedImage_pointer++;
  501. }
  502. }
  503.  
  504. //the main function of the unwrapper
  505. void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
  506. {
  507. //Declarations of getting two arrays from Matlab
  508. //1)input wrapped image of type float and 2)mask of type unsigned char
  509. float *WrappedImage = (float *)mxGetData(prhs[0]);
  510. int image_width = mxGetM(prhs[0]);
  511. int image_height = mxGetN(prhs[0]);
  512.  
  513. //declare a place to store the unwrapped image and return it to Matlab
  514. const mwSize *dims = mxGetDimensions(prhs[0]);
  515. plhs[0] = mxCreateNumericArray(2, dims, mxSINGLE_CLASS, mxREAL);
  516. float *UnwrappedImage = (float *)mxGetPr(plhs[0]);
  517.  
  518. int i, j;
  519. int image_size = image_height * image_width;
  520. int two_image_size = 2 * image_size;
  521.  
  522. int No_of_Edges = (image_width)*(image_height - 1) + (image_width - 1)*(image_height);
  523.  
  524. PIXEL *pixel = (PIXEL *)calloc(image_size, sizeof(PIXEL));
  525. EDGE *edge = (EDGE *)calloc(No_of_Edges, sizeof(EDGE));;
  526.  
  527. //initialise the pixels
  528. initialisePIXELs(WrappedImage, pixel, image_width, image_height);
  529.  
  530. calculate_reliability(WrappedImage, pixel, image_width, image_height);
  531.  
  532. horizentalEDGEs(pixel, edge, image_width, image_height);
  533.  
  534. verticalEDGEs(pixel, edge, image_width, image_height);
  535.  
  536. //sort the EDGEs depending on their reiability. The PIXELs with higher relibility (small value) first
  537. //if your code stuck because of the quicker_sort() function, then use the quick_sort() function
  538. //run only one of the two functions (quick_sort() or quicker_sort() )
  539. //quick_sort(edge, No_of_Edges);
  540. quicker_sort(edge, edge + No_of_Edges - 1);
  541.  
  542. //gather PIXELs into groups
  543. gatherPIXELs(edge, image_width, image_height);
  544.  
  545. //unwrap the whole image
  546. unwrapImage(pixel, image_width, image_height);
  547.  
  548. //copy the image from PIXEL structure to the wrapped phase array passed to this function
  549. returnImage(pixel, UnwrappedImage, image_width, image_height);
  550.  
  551. free(edge);
  552. free(pixel);
  553. return;
  554. }

https://www.mathworks.com/matlabcentral/fileexchange/65565-fast-2d-phase-unwrapping

https://blog.csdn.net/qq_35759050/article/details/74178395

相位展开(phase unwrapping)算法研究与实践的更多相关文章

  1. 【C#代码实战】群蚁算法理论与实践全攻略——旅行商等路径优化问题的新方法

    若干年前读研的时候,学院有一个教授,专门做群蚁算法的,很厉害,偶尔了解了一点点.感觉也是生物智能的一个体现,和遗传算法.神经网络有异曲同工之妙.只不过当时没有实际需求学习,所以没去研究.最近有一个这样 ...

  2. Akamai在内容分发网络中的算法研究(翻译总结)

    作者 | 钱坤 钱坤,腾讯后台开发工程师,从事领域为流媒体CDN相关,参与腾讯TVideo平台开发维护. 原文是<Algorithmic Nuggets in Content Delivery& ...

  3. 静态频繁子图挖掘算法用于动态网络——gSpan算法研究

    摘要 随着信息技术的不断发展,人类可以很容易地收集和储存大量的数据,然而,如何在海量的数据中提取对用户有用的信息逐渐地成为巨大挑战.为了应对这种挑战,数据挖掘技术应运而生,成为了最近一段时期数据科学的 ...

  4. 【初码干货】使用阿里云对Web开发中的资源文件进行CDN加速的深入研究和实践

    提示:阅读本文需提前了解的相关知识 1.阿里云(https://www.aliyun.com) 2.阿里云CDN(https://www.aliyun.com/product/cdn) 3.阿里云OS ...

  5. 机器学习算法与Python实践之(四)支持向量机(SVM)实现

    机器学习算法与Python实践之(四)支持向量机(SVM)实现 机器学习算法与Python实践之(四)支持向量机(SVM)实现 zouxy09@qq.com http://blog.csdn.net/ ...

  6. 机器学习算法与Python实践之(三)支持向量机(SVM)进阶

    机器学习算法与Python实践之(三)支持向量机(SVM)进阶 机器学习算法与Python实践之(三)支持向量机(SVM)进阶 zouxy09@qq.com http://blog.csdn.net/ ...

  7. 机器学习算法与Python实践之(二)支持向量机(SVM)初级

    机器学习算法与Python实践之(二)支持向量机(SVM)初级 机器学习算法与Python实践之(二)支持向量机(SVM)初级 zouxy09@qq.com http://blog.csdn.net/ ...

  8. July-程序员面试、算法研究、编程艺术、红黑树、数据挖掘5大经典原创系列集锦与总结

    程序员面试.算法研究.编程艺术.红黑树.数据挖掘5大经典原创系列集锦与总结 http://blog.csdn.net/v_july_v/article/details/6543438

  9. 经典算法研究系列:二、Dijkstra 算法初探

    July   二零一一年一月 本文主要参考:算法导论 第二版.维基百科. 一.Dijkstra 算法的介绍 Dijkstra 算法,又叫迪科斯彻算法(Dijkstra),算法解决的是有向图中单个源点到 ...

随机推荐

  1. 案例实战之如何写一个webpack plugin

    案例实战之如何写一个webpack plugin 1.写一个生成打包文件目录的file.md文件 // 生成一个目录项目目录的文件夹 class FileListPlugin { constructo ...

  2. scala 中的匹配模式

    unapply 仅作匹配,不作其它输出.返回 Boolean 值 object UpperCase { def unapply(s: String): Boolean = s.toUpperCase ...

  3. Kafaka 总结

    Kafka是一个分布式的Streaming处理平台,Kafka可以用于数据库中数据的导入导出,也可以用于实时流的处理,但是Kafka最核心的功能就是作为分布式的消息中间件. Kafka集群是由多个Br ...

  4. 5 Successful Business Models for Web-Based Open-Source Projects

    https://handsontable.com/blog/articles/2016/3/5-successful-business-models-for-web-based-open-source ...

  5. Django 中使用redis

    Django使用redis   方式一,使用Django-redis模块 #安装: pip3 install django-redis CACHES = { "default": ...

  6. 持续集成学习9 jenkins执行脚本

    一.配置 1.首先在slave节点上写一脚本 [root@node1 script]# cat /application/script/test.sh #!/bin/bash echo "h ...

  7. 从TEB到PEB再到SEH(二)

    什么是SEH? SEH( Structured Exception Handling , 结构化异常处理 ) 结构化异常处理(SEH)是Windows操作系统提供的强大异常处理功能.而Visual C ...

  8. python(二)——if条件语句与基本数据类型

    if语句 缩进要保持一致 if 1 == 1: print('hello') if 2 == 2: print('world') else: print('python') elif inp = in ...

  9. 推荐一款分布式微服务框架 Surging

    surging   surging 是一个分布式微服务框架,提供高性能RPC远程服务调用,采用Zookeeper.Consul作为surging服务的注册中心,集成了哈希,随机,轮询,压力最小优先作为 ...

  10. SQL基础-创建新的输出字段

    一.创建新的输出字段 1.建表.插数据 ### CREATE TABLE `t_stock_trans_dtl` ( `trans_id` varchar(100) NOT NULL COMMENT ...