JWS C Library
C language utility library
|
00001 /* 00002 * This work is licensed under a Creative Commons 00003 * Attribution-Noncommercial-Share Alike 3.0 United States License. 00004 * 00005 * http://creativecommons.org/licenses/by-nc-sa/3.0/us/ 00006 * 00007 * You are free: 00008 * 00009 * to Share - to copy, distribute, display, and perform the work 00010 * to Remix - to make derivative works 00011 * 00012 * Under the following conditions: 00013 * 00014 * Attribution. You must attribute the work in the manner specified by the 00015 * author or licensor (but not in any way that suggests that they endorse you 00016 * or your use of the work). 00017 * 00018 * Noncommercial. You may not use this work for commercial purposes. 00019 * 00020 * Share Alike. If you alter, transform, or build upon this work, you may 00021 * distribute the resulting work only under the same or similar license to 00022 * this one. 00023 * 00024 * For any reuse or distribution, you must make clear to others the license 00025 * terms of this work. The best way to do this is by including this header. 00026 * 00027 * Any of the above conditions can be waived if you get permission from the 00028 * copyright holder. 00029 * 00030 * Apart from the remix rights granted under this license, nothing in this 00031 * license impairs or restricts the author's moral rights. 00032 */ 00033 00034 00051 #include <jwsc/config.h> 00052 00053 #include <stdlib.h> 00054 #include <stdio.h> 00055 #include <inttypes.h> 00056 #include <assert.h> 00057 #include <math.h> 00058 #include <string.h> 00059 #include <errno.h> 00060 00061 #include "jwsc/base/error.h" 00062 #include "jwsc/vector/vector.h" 00063 #include "jwsc/vector/vector_math.h" 00064 #include "jwsc/matblock/matblock.h" 00065 #include "jwsc/matblock/matblock_fft.h" 00066 #include "jwsc/matblock/matblock_conv.h" 00067 #include "jwsc/filter/3d.h" 00068 #include "jwsc/prob/pmf.h" 00069 #include "jwsc/imgblock/surface.h" 00070 00071 #ifdef JWSC_HAVE_DMALLOC 00072 #include <dmalloc.h> 00073 #endif 00074 00075 00077 #define INV_SQRT_2 0.70710678 00078 00079 00081 #define INV_SQRT_3 0.57735027 00082 00083 00090 typedef struct 00091 { 00093 float dcol; 00094 00096 float drow; 00097 00099 float dmat; 00100 00102 float mag; 00103 00105 uint8_t marked; 00106 } 00107 Gradient_f; 00108 00109 00111 static Error* create_gradient_map_f 00112 ( 00113 Gradient_f**** map_out, 00114 const Matblock_f* m, 00115 float sigma, 00116 float grad_mat_weight, 00117 float grad_row_weight, 00118 float grad_col_weight 00119 ) 00120 { 00121 uint32_t num_mats, num_rows, num_cols; 00122 uint32_t mat, row, col; 00123 float dmat, dcol, drow; 00124 00125 Matblock_f* gauss = NULL; 00126 Matblock_f* m_dmat = NULL; 00127 Matblock_f* m_drow = NULL; 00128 Matblock_f* m_dcol = NULL; 00129 Gradient_f*** map; 00130 Gradient_f** map_rows; 00131 Gradient_f* map_elts; 00132 Error* e; 00133 00134 num_mats = m->num_mats; 00135 num_rows = m->num_rows; 00136 num_cols = m->num_cols; 00137 00138 assert(*map_out == NULL); 00139 00140 #ifdef JWSC_HAVE_FFTW3F 00141 if ((e = create_3d_gaussian_dx_filter_f(&gauss, sigma, sigma, sigma, 00142 num_mats, num_rows, num_cols)) != NULL) 00143 { 00144 return e; 00145 } 00146 shift_matblock_f(&gauss, gauss); 00147 assert(convolve_matblock_fft_f(&m_dcol, m, gauss) == NULL); 00148 00149 if ((e = create_3d_gaussian_dy_filter_f(&gauss, sigma, sigma, sigma, 00150 num_mats, num_rows, num_cols)) != NULL) 00151 { 00152 return e; 00153 } 00154 shift_matblock_f(&gauss, gauss); 00155 assert(convolve_matblock_fft_f(&m_drow, m, gauss) == NULL); 00156 00157 if ((e = create_3d_gaussian_dz_filter_f(&gauss, sigma, sigma, sigma, 00158 num_mats, num_rows, num_cols)) != NULL) 00159 { 00160 return e; 00161 } 00162 shift_matblock_f(&gauss, gauss); 00163 assert(convolve_matblock_fft_f(&m_dmat, m, gauss) == NULL); 00164 #else 00165 if ((e = create_auto_3d_gaussian_dx_filter_f(&gauss, sigma, sigma, 00166 sigma)) != NULL) 00167 { 00168 return e; 00169 } 00170 assert(convolve_matblock_f(&m_dcol, m, gauss) == NULL); 00171 00172 if ((e = create_auto_3d_gaussian_dy_filter_f(&gauss, sigma, sigma, 00173 sigma)) != NULL) 00174 { 00175 return e; 00176 } 00177 assert(convolve_matblock_f(&m_drow, m, gauss) == NULL); 00178 00179 if ((e = create_auto_3d_gaussian_dz_filter_f(&gauss, sigma, sigma, 00180 sigma)) != NULL) 00181 { 00182 return e; 00183 } 00184 assert(convolve_matblock_f(&m_dmat, m, gauss) == NULL); 00185 #endif 00186 00187 free_matblock_f(gauss); 00188 00189 assert(map_elts = malloc(num_mats*num_rows*num_cols * sizeof(Gradient_f))); 00190 assert(map_rows = malloc(num_mats*num_rows*sizeof(Gradient_f*))); 00191 assert(*map_out = malloc(num_mats*sizeof(Gradient_f**))); 00192 map = *map_out; 00193 00194 for (mat = 0; mat < num_mats; mat++) 00195 { 00196 map[ mat ] = &(map_rows[ mat*num_rows ]); 00197 00198 for (row = 0; row < num_rows; row++) 00199 { 00200 map[ mat ][ row ] = &(map_elts[ (row+mat*num_rows)*num_cols ]); 00201 } 00202 } 00203 00204 for (mat = 0; mat < num_mats; mat++) 00205 { 00206 for (row = 0; row < num_rows; row++) 00207 { 00208 for (col = 0; col < num_cols; col++) 00209 { 00210 dcol = m_dcol->elts[ mat ][ row ][ col ]; 00211 drow = m_drow->elts[ mat ][ row ][ col ]; 00212 dmat = m_dmat->elts[ mat ][ row ][ col ]; 00213 00214 map[ mat ][ row ][ col ].dcol = dcol; 00215 map[ mat ][ row ][ col ].drow = drow; 00216 map[ mat ][ row ][ col ].dmat = dmat; 00217 map[ mat ][ row ][ col ].mag = sqrt(grad_col_weight*dcol*dcol + 00218 grad_row_weight*drow*drow + 00219 grad_mat_weight*dmat*dmat); 00220 map[ mat ][ row ][ col ].marked = 0; 00221 00222 if (map[ mat ][ row ][ col ].mag >= 1.0e-8) 00223 { 00224 map[ mat ][ row ][ col ].dcol /= 00225 map[ mat ][ row ][ col ].mag; 00226 map[ mat ][ row ][ col ].drow /= 00227 map[ mat ][ row ][ col ].mag; 00228 map[ mat ][ row ][ col ].dmat /= 00229 map[ mat ][ row ][ col ].mag; 00230 } 00231 } 00232 } 00233 } 00234 00235 free_matblock_f(m_dcol); 00236 free_matblock_f(m_drow); 00237 free_matblock_f(m_dmat); 00238 00239 return NULL; 00240 } 00241 00242 00244 static Gradient_f* follow_gradient_f 00245 ( 00246 int32_t* grad_mat_in_out, 00247 int32_t* grad_row_in_out, 00248 int32_t* grad_col_in_out, 00249 float dir_x, 00250 float dir_y, 00251 float dir_z, 00252 Gradient_f*** map, 00253 uint32_t num_mats, 00254 uint32_t num_rows, 00255 uint32_t num_cols 00256 ) 00257 { 00258 static const int neighbor_positions[ 26 ][ 3 ] = { 00259 {1,0,1},{1,1,1},{0,1,1},{-1,1,1},{-1,0,1},{-1,-1,1},{0,-1,1},{1,-1,1}, 00260 {0,0,1},{1,0,0},{1,1,0},{0,1,0},{-1,1,0},{-1,0,0},{-1,-1,0},{0,-1,0}, 00261 {1,-1,0},{1,0,-1},{1,1,-1},{0,1,-1},{-1,1,-1},{-1,0,-1},{-1,-1,-1}, 00262 {0,-1,-1},{1,-1,-1},{0,0,-1} }; 00263 static const float neighbor_vectors[ 26 ][ 3 ] = { 00264 {INV_SQRT_2,0,INV_SQRT_2}, {INV_SQRT_3,INV_SQRT_3,INV_SQRT_3}, 00265 {0,INV_SQRT_2,INV_SQRT_2}, {-INV_SQRT_3,INV_SQRT_3,INV_SQRT_3}, 00266 {-INV_SQRT_2,0,INV_SQRT_2}, {-INV_SQRT_3,-INV_SQRT_3,INV_SQRT_3}, 00267 {0,-INV_SQRT_2,INV_SQRT_2}, {INV_SQRT_3,-INV_SQRT_3,INV_SQRT_3}, 00268 {0,0,1}, {1,0,0}, {INV_SQRT_2,INV_SQRT_2,0}, {0,1,0}, 00269 {-INV_SQRT_2,INV_SQRT_2,0}, {-1,0,0}, {-INV_SQRT_2,-INV_SQRT_2,0}, 00270 {0,-1,0}, {INV_SQRT_2,-INV_SQRT_2,0}, {INV_SQRT_2,0,-INV_SQRT_2}, 00271 {INV_SQRT_3,INV_SQRT_3,-INV_SQRT_3}, {0,INV_SQRT_2,-INV_SQRT_2}, 00272 {-INV_SQRT_3,INV_SQRT_3,-INV_SQRT_3}, {-INV_SQRT_2,0,-INV_SQRT_2}, 00273 {-INV_SQRT_3,-INV_SQRT_3,-INV_SQRT_3}, {0,-INV_SQRT_2,-INV_SQRT_2}, 00274 {INV_SQRT_3,-INV_SQRT_3,-INV_SQRT_3},{0,0,-1} }; 00275 00276 uint16_t i; 00277 uint16_t max_neighbor; 00278 int32_t grad_col, grad_row, grad_mat; 00279 float max_dp; 00280 float dp; 00281 00282 Gradient_f* grad; 00283 00284 grad_col = *grad_col_in_out; 00285 grad_row = *grad_row_in_out; 00286 grad_mat = *grad_mat_in_out; 00287 00288 grad = &(map[ grad_mat ][ grad_row ][ grad_col ]); 00289 max_neighbor = 0; 00290 max_dp = dir_x * neighbor_vectors[ 0 ][ 0 ] + 00291 dir_y * neighbor_vectors[ 0 ][ 1 ] + 00292 dir_z * neighbor_vectors[ 0 ][ 2 ]; 00293 00294 for (i = 1; i < 26; i++) 00295 { 00296 dp = dir_x * neighbor_vectors[ i ][ 0 ] + 00297 dir_y * neighbor_vectors[ i ][ 1 ] + 00298 dir_z * neighbor_vectors[ i ][ 2 ]; 00299 00300 /* Should have some stochastic tie-breaker here. */ 00301 if (dp >= max_dp) 00302 { 00303 max_dp = dp; 00304 max_neighbor = i; 00305 } 00306 } 00307 00308 grad_mat += neighbor_positions[ max_neighbor ][ 2 ]; 00309 grad_row += neighbor_positions[ max_neighbor ][ 1 ]; 00310 grad_col += neighbor_positions[ max_neighbor ][ 0 ]; 00311 00312 if (grad_mat == -1) 00313 grad_mat = 0; 00314 else if (grad_mat == num_mats) 00315 grad_mat = num_mats-1; 00316 00317 if (grad_row == -1) 00318 grad_row = 0; 00319 else if (grad_row == num_rows) 00320 grad_row = num_rows-1; 00321 00322 if (grad_col == -1) 00323 grad_col = 0; 00324 else if (grad_col == num_cols) 00325 grad_col = num_cols-1; 00326 00327 *grad_col_in_out = grad_col; 00328 *grad_row_in_out = grad_row; 00329 *grad_mat_in_out = grad_mat; 00330 00331 return &map[ grad_mat ][ grad_row ][ grad_col ]; 00332 } 00333 00334 00336 static Gradient_f* get_maximal_along_gradient_f 00337 ( 00338 int32_t* grad_mat_in_out, 00339 int32_t* grad_row_in_out, 00340 int32_t* grad_col_in_out, 00341 Gradient_f*** map, 00342 uint32_t num_mats, 00343 uint32_t num_rows, 00344 uint32_t num_cols 00345 ) 00346 { 00347 int32_t grad_mat, grad_row, grad_col; 00348 int32_t curr_grad_mat, curr_grad_row, curr_grad_col; 00349 int32_t next_grad_mat, next_grad_row, next_grad_col; 00350 int32_t prev_grad_mat, prev_grad_row, prev_grad_col; 00351 00352 Gradient_f* curr_grad; 00353 Gradient_f* next_grad; 00354 Gradient_f* prev_grad; 00355 Gradient_f* max_grad; 00356 00357 grad_mat = *grad_mat_in_out; 00358 grad_row = *grad_row_in_out; 00359 grad_col = *grad_col_in_out; 00360 00361 curr_grad_mat = grad_mat; 00362 curr_grad_row = grad_row; 00363 curr_grad_col = grad_col; 00364 curr_grad = &map[ curr_grad_mat ][ curr_grad_row ][ curr_grad_col ]; 00365 00366 prev_grad_mat = curr_grad_mat; 00367 prev_grad_row = curr_grad_row; 00368 prev_grad_col = curr_grad_col; 00369 prev_grad = follow_gradient_f(&prev_grad_mat, &prev_grad_row, 00370 &prev_grad_col, -(curr_grad->dcol), 00371 -(curr_grad->drow), -(curr_grad->dmat), 00372 map, num_mats, num_rows, num_cols); 00373 00374 next_grad_mat = curr_grad_mat; 00375 next_grad_row = curr_grad_row; 00376 next_grad_col = curr_grad_col; 00377 next_grad = follow_gradient_f(&next_grad_mat, &next_grad_row, 00378 &next_grad_col, curr_grad->dcol, 00379 curr_grad->drow, curr_grad->dmat, map, 00380 num_mats, num_rows, num_cols); 00381 00382 max_grad = NULL; 00383 while (max_grad == NULL) 00384 { 00385 if (curr_grad->mag >= next_grad->mag && 00386 curr_grad->mag >= prev_grad->mag) 00387 { 00388 max_grad = curr_grad; 00389 } 00390 else if (curr_grad->mag >= prev_grad->mag) 00391 { 00392 curr_grad_mat = next_grad_mat; 00393 curr_grad_row = next_grad_row; 00394 curr_grad_col = next_grad_col; 00395 curr_grad = next_grad; 00396 } 00397 else 00398 { 00399 curr_grad_mat = prev_grad_mat; 00400 curr_grad_row = prev_grad_row; 00401 curr_grad_col = prev_grad_col; 00402 curr_grad = prev_grad; 00403 } 00404 00405 prev_grad_mat = curr_grad_mat; 00406 prev_grad_row = curr_grad_row; 00407 prev_grad_col = curr_grad_col; 00408 prev_grad = follow_gradient_f(&prev_grad_mat, &prev_grad_row, 00409 &prev_grad_col, -(curr_grad->dcol), 00410 -(curr_grad->drow), 00411 -(curr_grad->dmat), map, 00412 num_mats, num_rows, num_cols); 00413 00414 next_grad_mat = curr_grad_mat; 00415 next_grad_row = curr_grad_row; 00416 next_grad_col = curr_grad_col; 00417 next_grad = follow_gradient_f(&next_grad_mat, &next_grad_row, 00418 &next_grad_col, curr_grad->dcol, 00419 curr_grad->drow, curr_grad->dmat, 00420 map, num_mats, num_rows, num_cols); 00421 } 00422 00423 *grad_mat_in_out = curr_grad_mat; 00424 *grad_row_in_out = curr_grad_row; 00425 *grad_col_in_out = curr_grad_col; 00426 00427 return max_grad; 00428 } 00429 00430 00437 static void follow_surface_f 00438 ( 00439 Gradient_f* grad, 00440 int32_t grad_mat, 00441 int32_t grad_row, 00442 int32_t grad_col, 00443 Gradient_f*** map, 00444 uint32_t num_mats, 00445 uint32_t num_rows, 00446 uint32_t num_cols, 00447 float end_thresh 00448 ) 00449 { 00450 /* Vectors orthogonal to the z-axis. */ 00451 static const float orthogonal_vectors[ 8 ][ 3 ] = { 00452 {1,0,0}, {INV_SQRT_2,INV_SQRT_2,0},{0,1,0}, {-INV_SQRT_2,INV_SQRT_2,0}, 00453 {-1,0,0}, {-INV_SQRT_2,-INV_SQRT_2,0}, {0,-1,0}, 00454 {INV_SQRT_2,-INV_SQRT_2,0} }; 00455 00456 uint8_t i; 00457 float x, y, z; 00458 float ortho_x, ortho_y, ortho_z; 00459 float sin_psi, cos_psi; 00460 float sin_theta, cos_theta; 00461 float mag_xy; 00462 00463 Gradient_f* grad_to_follow = NULL; 00464 00465 /* psi used to rotate around z-axis to put vector on the yz-plane. */ 00466 mag_xy = sqrt(grad->dcol*grad->dcol + 00467 grad->drow*grad->drow); 00468 if (mag_xy > 1.0e-8) 00469 { 00470 cos_psi = grad->drow / mag_xy; 00471 sin_psi = grad->dcol / mag_xy; 00472 } 00473 else 00474 { 00475 cos_psi = 0.0; 00476 sin_psi = 1.0; 00477 } 00478 00479 /* theta used to rotate around x-axis to put vector onto the z-axis. */ 00480 cos_theta = grad->dmat; 00481 sin_theta = mag_xy; 00482 00483 /* Rotate each orthogonal vector and follow the gradient in that 00484 * direction. */ 00485 for (i = 0; i < 8; i++) 00486 { 00487 ortho_x = orthogonal_vectors[ i ][ 0 ]; 00488 ortho_y = orthogonal_vectors[ i ][ 1 ]; 00489 ortho_z = orthogonal_vectors[ i ][ 2 ]; 00490 00491 /* Rotate the orthagonals. */ 00492 x = cos_psi*ortho_x + cos_theta*sin_psi*ortho_y + 00493 sin_theta*sin_psi*ortho_z; 00494 y = -sin_psi*ortho_x + cos_theta*cos_psi*ortho_y + 00495 cos_psi*sin_theta*ortho_z; 00496 z = -sin_theta*ortho_y + cos_theta*ortho_z; 00497 00498 follow_gradient_f(&grad_mat, &grad_row, &grad_col, x, y, z, map, 00499 num_mats, num_rows, num_cols); 00500 00501 grad_to_follow = get_maximal_along_gradient_f(&grad_mat, &grad_row, 00502 &grad_col, map, num_mats, num_rows, num_cols); 00503 00504 if (!grad_to_follow->marked && grad_to_follow->mag >= end_thresh && 00505 grad_mat > 0 && grad_mat < num_mats-1 && 00506 grad_row > 0 && grad_row < num_rows-1 && 00507 grad_col > 0 && grad_col < num_cols-1) 00508 { 00509 grad_to_follow->marked = 1; 00510 00511 follow_surface_f(grad_to_follow, grad_mat, grad_row, grad_col, 00512 map, num_mats, num_rows, num_cols, end_thresh); 00513 } 00514 } 00515 } 00516 00517 00524 static void get_surface_points_from_gradient_map_f 00525 ( 00526 Surface_point_f** pts_out, 00527 uint32_t* num_pts_out, 00528 const Matblock_f* m, 00529 Gradient_f*** map, 00530 uint32_t num_mats, 00531 uint32_t num_rows, 00532 uint32_t num_cols, 00533 float begin_thresh, 00534 float end_thresh 00535 ) 00536 { 00537 int32_t grad_mat; 00538 int32_t grad_row; 00539 int32_t grad_col; 00540 uint32_t mat, row, col; 00541 uint32_t num_pts; 00542 00543 Gradient_f* grad; 00544 Gradient_f* max_grad; 00545 Surface_point_f* pts; 00546 00547 for (mat = 0; mat < num_mats; mat++) 00548 { 00549 for (row = 0; row < num_rows; row++) 00550 { 00551 for (col = 0; col < num_cols; col++) 00552 { 00553 grad = &map[ mat ][ row ][ col ]; 00554 00555 if (!grad->marked && grad->mag >= begin_thresh) 00556 { 00557 grad_mat = mat; 00558 grad_row = row; 00559 grad_col = col; 00560 00561 max_grad = get_maximal_along_gradient_f(&grad_mat, 00562 &grad_row, &grad_col, map, num_mats, num_rows, 00563 num_cols); 00564 00565 if (!max_grad->marked && 00566 grad_mat > 0 && grad_mat < num_mats-1 && 00567 grad_row > 0 && grad_row < num_rows-1 && 00568 grad_col > 0 && grad_col < num_cols-1) 00569 { 00570 max_grad->marked = 1; 00571 00572 follow_surface_f(max_grad, grad_mat, grad_row, 00573 grad_col, map, num_mats, num_rows, num_cols, 00574 end_thresh); 00575 } 00576 } 00577 } 00578 } 00579 } 00580 00581 num_pts = 0; 00582 for (mat = 0; mat < num_mats; mat++) 00583 { 00584 for (row = 0; row < num_rows; row++) 00585 { 00586 for (col = 0; col < num_cols; col++) 00587 { 00588 if (map[ mat ][ row ][ col ].marked) 00589 { 00590 num_pts++; 00591 } 00592 } 00593 } 00594 } 00595 00596 *num_pts_out = num_pts; 00597 *pts_out = realloc(*pts_out, num_pts*sizeof(Surface_point_f)); 00598 if (num_pts > 0) assert(*pts_out); 00599 pts = *pts_out; 00600 00601 for (mat = 0; mat < num_mats; mat++) 00602 { 00603 for (row = 0; row < num_rows; row++) 00604 { 00605 for (col = 0; col < num_cols; col++) 00606 { 00607 grad = &map[ mat ][ row ][ col ]; 00608 if (grad->marked) 00609 { 00610 pts->mat = mat; 00611 pts->row = row; 00612 pts->col = col; 00613 pts->dcol = grad->dcol * grad->mag; 00614 pts->drow = grad->drow * grad->mag; 00615 pts->dmat = grad->dmat * grad->mag; 00616 pts->intensity = m->elts[ mat ][ row ][ col ]; 00617 pts++; 00618 } 00619 } 00620 } 00621 } 00622 } 00623 00624 00625 00626 00672 Error* detect_imgblock_surface_points_f 00673 ( 00674 Surface_point_f** r_pts_out, 00675 uint32_t* num_r_pts_out, 00676 Surface_point_f** g_pts_out, 00677 uint32_t* num_g_pts_out, 00678 Surface_point_f** b_pts_out, 00679 uint32_t* num_b_pts_out, 00680 const Imgblock_f* img, 00681 float sigma, 00682 float grad_img_weight, 00683 float grad_row_weight, 00684 float grad_col_weight, 00685 float begin_thresh, 00686 float end_thresh 00687 ) 00688 { 00689 Matblock_f* m = NULL; 00690 Error* e; 00691 00692 create_matblock_from_imgblock_f(&m, img, 1.0, 0.0, 0.0); 00693 if ((e = detect_matblock_surface_points_f(r_pts_out, num_r_pts_out, m, 00694 sigma, grad_img_weight, grad_row_weight, grad_col_weight, 00695 begin_thresh, end_thresh)) != NULL) 00696 { 00697 return e; 00698 } 00699 00700 create_matblock_from_imgblock_f(&m, img, 0.0, 1.0, 0.0); 00701 if ((e = detect_matblock_surface_points_f(g_pts_out, num_g_pts_out, m, 00702 sigma, grad_img_weight, grad_row_weight, grad_col_weight, 00703 begin_thresh, end_thresh)) != NULL) 00704 { 00705 return e; 00706 } 00707 00708 create_matblock_from_imgblock_f(&m, img, 0.0, 0.0, 1.0); 00709 if ((e = detect_matblock_surface_points_f(b_pts_out, num_b_pts_out, m, 00710 sigma, grad_img_weight, grad_row_weight, grad_col_weight, 00711 begin_thresh, end_thresh)) != NULL) 00712 { 00713 return e; 00714 } 00715 00716 free_matblock_f(m); 00717 00718 return NULL; 00719 } 00720 00760 Error* detect_matblock_surface_points_f 00761 ( 00762 Surface_point_f** pts_out, 00763 uint32_t* num_pts_out, 00764 const Matblock_f* m, 00765 float sigma, 00766 float grad_mat_weight, 00767 float grad_row_weight, 00768 float grad_col_weight, 00769 float begin_thresh, 00770 float end_thresh 00771 ) 00772 { 00773 Gradient_f*** map = NULL; 00774 Error* e; 00775 00776 if ((e = create_gradient_map_f(&map, m, sigma, grad_mat_weight, 00777 grad_row_weight, grad_col_weight)) != NULL) 00778 { 00779 free(*pts_out); *pts_out = NULL; 00780 return e; 00781 } 00782 00783 get_surface_points_from_gradient_map_f(pts_out, num_pts_out, m, map, 00784 m->num_mats, m->num_rows, m->num_cols, begin_thresh, end_thresh); 00785 00786 free(**map); 00787 free(*map); 00788 free(map); 00789 00790 return NULL; 00791 } 00792 00817 void sample_surface_points_f 00818 ( 00819 Surface_point_f** pts_out, 00820 uint32_t* num_pts_out, 00821 const Surface_point_f* pts_in, 00822 uint32_t num_pts_in, 00823 float p 00824 ) 00825 { 00826 uint32_t num_pts; 00827 uint32_t pt; 00828 Surface_point_f* pts; 00829 00830 *pts_out = realloc(*pts_out, num_pts_in*sizeof(Surface_point_f)); 00831 if (num_pts_in < 0) assert(*pts_out); 00832 00833 pts = *pts_out; 00834 num_pts = 0; 00835 00836 for (pt = 0; pt < num_pts_in; pt++) 00837 { 00838 if (sample_bernoulli_pmf_d(p)) 00839 { 00840 pts->mat = pts_in[ pt ].mat; 00841 pts->row = pts_in[ pt ].row; 00842 pts->col = pts_in[ pt ].col; 00843 pts->dcol = pts_in[ pt ].dcol; 00844 pts->drow = pts_in[ pt ].drow; 00845 pts->dmat = pts_in[ pt ].dmat; 00846 pts->intensity = pts_in[ pt ].intensity; 00847 pts++; 00848 num_pts++; 00849 } 00850 } 00851 00852 *pts_out = realloc(*pts_out, num_pts*sizeof(Surface_point_f)); 00853 if (num_pts > 0) assert(*pts_out); 00854 00855 *num_pts_out = num_pts; 00856 } 00857 00878 void color_surface_points_f 00879 ( 00880 Imgblock_f** img_out, 00881 const Imgblock_f* img_in, 00882 const Surface_point_f* pts, 00883 uint32_t num_pts, 00884 const Pixel_f* pxl 00885 ) 00886 { 00887 uint32_t pt; 00888 Imgblock_f* img; 00889 00890 copy_imgblock_f(img_out, img_in); 00891 img = *img_out; 00892 00893 for (pt = 0; pt < num_pts; pt++) 00894 { 00895 img->pxls[ pts[ pt ].mat ][ pts[ pt ].row ][ pts[ pt ].col ] = *pxl; 00896 } 00897 } 00898 00936 Error* read_surface_points_f 00937 ( 00938 Surface_point_f** pts_out, 00939 uint32_t* num_pts_out, 00940 const char* fname 00941 ) 00942 { 00943 uint32_t num_pts; 00944 uint32_t p; 00945 FILE* fp; 00946 00947 Surface_point_f* pts; 00948 Surface_point_f* pt; 00949 00950 if ((fp = fopen(fname, "r")) == NULL) 00951 { 00952 free(*pts_out); *pts_out = NULL; 00953 return JWSC_EIO(strerror(errno)); 00954 } 00955 00956 if (fscanf(fp, "num_pts=%u\n", &num_pts) != 1) 00957 { 00958 free(*pts_out); *pts_out = NULL; 00959 return JWSC_EARG("File not properly formatted to read surface points"); 00960 } 00961 00962 *num_pts_out = num_pts; 00963 *pts_out = realloc(*pts_out, num_pts*sizeof(Surface_point_f)); 00964 if (num_pts > 0) assert(*pts_out); 00965 pts = *pts_out; 00966 00967 for (p = 0; p < num_pts; p++) 00968 { 00969 pt = &((*pts_out)[ p ]); 00970 00971 if (fscanf(fp, "col=%u row=%u mat=%u dcol=%f drow=%f dmat=%f intensity=%f\n", 00972 &(pt->col), &(pt->row), &(pt->mat), 00973 &(pt->dcol), &(pt->drow), &(pt->dmat), 00974 &(pt->intensity)) != 7) 00975 { 00976 free(*pts_out); *pts_out = NULL; 00977 return JWSC_EARG("Surface points file not properly formatted"); 00978 } 00979 } 00980 00981 if (fclose(fp) != 0) 00982 { 00983 free(*pts_out); *pts_out = NULL; 00984 return JWSC_EIO(strerror(errno)); 00985 } 00986 00987 return NULL; 00988 } 00989 01022 Error* write_surface_points_f 01023 ( 01024 const Surface_point_f* pts, 01025 uint32_t num_pts, 01026 const char* fname 01027 ) 01028 { 01029 uint32_t p; 01030 FILE* fp; 01031 01032 const Surface_point_f* pt; 01033 01034 if ((fp = fopen(fname, "w")) == NULL) 01035 { 01036 return JWSC_EIO(strerror(errno)); 01037 } 01038 01039 fprintf(fp, "num_pts=%u\n", num_pts); 01040 01041 for (p = 0; p < num_pts; p++) 01042 { 01043 pt = &(pts[ p ]); 01044 01045 fprintf(fp, "col=%u row=%u mat=%u", pt->col, pt->row, pt->mat); 01046 fprintf(fp, " dcol=%f drow=%f dmat=%f", pt->dcol, pt->drow, pt->dmat); 01047 fprintf(fp, " intensity=%f\n", pt->intensity); 01048 } 01049 01050 if (fclose(fp) != 0) 01051 { 01052 return JWSC_EIO(strerror(errno)); 01053 } 01054 01055 return NULL; 01056 } 01057 01080 void create_surface_patch_f 01081 ( 01082 Surface_patch_f** patch_out, 01083 const Surface_point_f* point, 01084 float size, 01085 float x_scale, 01086 float y_scale, 01087 float z_scale 01088 ) 01089 { 01090 double mag_xy; 01091 double cos_psi, sin_psi; 01092 double cos_theta, sin_theta; 01093 double pt_x, pt_y, pt_z; 01094 double rot_pt_x, rot_pt_y, rot_pt_z; 01095 01096 uint32_t i; 01097 01098 Surface_patch_f* patch; 01099 01100 if (*patch_out == NULL) 01101 { 01102 assert(*patch_out = malloc(sizeof(Surface_patch_f))); 01103 for (i = 0; i < 4; i++) 01104 { 01105 (*patch_out)->pts[i] = NULL; 01106 create_vector_f(&((*patch_out)->pts[i]), 3); 01107 } 01108 (*patch_out)->normal = NULL; 01109 (*patch_out)->center = NULL; 01110 create_vector_f(&((*patch_out)->normal), 3); 01111 create_vector_f(&((*patch_out)->center), 3); 01112 } 01113 patch = *patch_out; 01114 01115 patch->albedo = point->intensity; 01116 01117 patch->center->elts[0] = point->col; 01118 patch->center->elts[1] = point->row; 01119 patch->center->elts[2] = point->mat; 01120 01121 patch->normal->elts[0] = point->dcol; 01122 patch->normal->elts[1] = point->drow; 01123 patch->normal->elts[2] = point->dmat; 01124 normalize_vector_mag_f(&(patch->normal), patch->normal); 01125 01126 /* Patch's starting orientation is centered at the origin on the x,y 01127 * plane. */ 01128 patch->pts[0]->elts[0] = size; 01129 patch->pts[0]->elts[1] = size; 01130 patch->pts[0]->elts[2] = 0; 01131 01132 patch->pts[1]->elts[0] = size; 01133 patch->pts[1]->elts[1] =-size; 01134 patch->pts[1]->elts[2] = 0; 01135 01136 patch->pts[2]->elts[0] =-size; 01137 patch->pts[2]->elts[1] =-size; 01138 patch->pts[2]->elts[2] = 0; 01139 01140 patch->pts[3]->elts[0] =-size; 01141 patch->pts[3]->elts[1] = size; 01142 patch->pts[3]->elts[2] = 0; 01143 01144 /* Transorm the patch points according to the center and normal. */ 01145 01146 /* 1. The points on the patch need to be rotated by the normal vector. 01147 * psi used to rotate around z-axis to put points on the yz-plane. */ 01148 mag_xy = sqrt(patch->normal->elts[0]*patch->normal->elts[0] + 01149 patch->normal->elts[1]*patch->normal->elts[1]); 01150 if (mag_xy > 1.0e-8) 01151 { 01152 cos_psi = patch->normal->elts[1] / mag_xy; 01153 sin_psi = patch->normal->elts[0] / mag_xy; 01154 } 01155 else 01156 { 01157 cos_psi = 0.0; 01158 sin_psi = 1.0; 01159 } 01160 01161 /* 2. Theta used to rotate around x-axis to put points onto the z-axis. */ 01162 cos_theta = patch->normal->elts[2]; 01163 sin_theta = mag_xy; 01164 01165 /* Transform the patch points. */ 01166 for (i = 0; i < 4; i++) 01167 { 01168 /* Rotate. */ 01169 pt_x = patch->pts[ i ]->elts[0]; 01170 pt_y = patch->pts[ i ]->elts[1]; 01171 pt_z = patch->pts[ i ]->elts[2]; 01172 01173 rot_pt_x = cos_psi*pt_x + cos_theta*sin_psi*pt_y + 01174 sin_theta*sin_psi*pt_z; 01175 rot_pt_y = -sin_psi*pt_x + cos_theta*cos_psi*pt_y + 01176 cos_psi*sin_theta*pt_z; 01177 rot_pt_z = -sin_theta*pt_y + cos_theta*pt_z; 01178 01179 patch->pts[ i ]->elts[0] = rot_pt_x; 01180 patch->pts[ i ]->elts[1] = rot_pt_y; 01181 patch->pts[ i ]->elts[2] = rot_pt_z; 01182 01183 /* Translate. */ 01184 add_vectors_f(&(patch->pts[ i ]), patch->pts[ i ], patch->center); 01185 01186 /* Scale. */ 01187 patch->pts[ i ]->elts[0] *= x_scale; 01188 patch->pts[ i ]->elts[1] *= y_scale; 01189 patch->pts[ i ]->elts[2] *= z_scale; 01190 } 01191 01192 /* Finally, scale the position of the center point. */ 01193 patch->center->elts[0] *= x_scale; 01194 patch->center->elts[1] *= y_scale; 01195 patch->center->elts[2] *= z_scale; 01196 } 01197 01211 void free_surface_patch_f(Surface_patch_f* patch) 01212 { 01213 free_vector_f(patch->pts[0]); 01214 free_vector_f(patch->pts[1]); 01215 free_vector_f(patch->pts[2]); 01216 free_vector_f(patch->pts[3]); 01217 free_vector_f(patch->normal); 01218 free_vector_f(patch->center); 01219 free(patch); 01220 } 01221