Advertisement
Guest User

Untitled

a guest
Mar 4th, 2015
209
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.54 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #include <cv.h>
  6. #include <highgui.h>
  7.  
  8. #include "building.h"
  9. #include "functools.h"
  10. #include "utils.h"
  11.  
  12. #define LINE_SIZE 1024
  13.  
  14. #define SKIP_LINE( no ) if ( no == NULL ) { printf( "Skipping\n" ); continue; }
  15.  
  16. #define H 0
  17. #define S 1
  18. #define V 2
  19.  
  20. #define STEP1_WIN_NAME "STEP 1"
  21. #define STEP2_WIN_NAME "STEP 2"
  22. #define ZOOM           1
  23.  
  24. #define RESAMPLE       1.0f
  25.  
  26. typedef struct MouseProbe {
  27.     int x;
  28.     int y;
  29.  
  30.     IplImage *img;
  31.     IplImage *show_img;
  32.     IplImage *edge_img;
  33. } MouseProbe;
  34.  
  35. // variables
  36.  
  37.  
  38. // function declarations
  39. void flood_fill(IplImage *src_img, IplImage *dst_img, IplImage *height_img, const int x, const int y);
  40.  
  41.  
  42. /**
  43. * Callback pro kliknuti mysi.
  44. * param - obsahuje poiter na libovolna data, ktera mu predame pri vytvareni callbacku
  45. */
  46. void mouse_probe_handler(int event, int x, int y, int flags, void* param) {
  47.     MouseProbe *probe = (MouseProbe*)param;
  48.  
  49.     switch (event) {
  50.  
  51.     case CV_EVENT_LBUTTONDOWN:
  52.         printf("Clicked LEFT at: [ %d, %d ]\n", x, y);
  53.         flood_fill(probe->edge_img, probe->show_img, probe->img, x, y);
  54.         break;
  55.  
  56.     case CV_EVENT_RBUTTONDOWN:
  57.         printf("Clicked RIGHT at: [ %d, %d ]\n", x, y);
  58.         break;
  59.     }
  60. }
  61.  
  62.  
  63. void create_windows(const int width, const int height) {
  64.     cvNamedWindow(STEP1_WIN_NAME, 0);
  65.     cvNamedWindow(STEP2_WIN_NAME, 0);
  66.  
  67.     cvResizeWindow(STEP1_WIN_NAME, width*ZOOM, height*ZOOM);
  68.     cvResizeWindow(STEP2_WIN_NAME, width*ZOOM, height*ZOOM);
  69.  
  70. } // create_windows
  71.  
  72.  
  73. /**
  74. * Provede flood fill ze zadaneho bodu (x, y) pro okolni body pokud obsahuji stejnou hodnotu,
  75. * jaka prisla v argumentu value. Funkce rekurzivne vola sama sebe pro sve 4-okoli.
  76. * src_img - obraz na kterem se bude provadet vyplnovani
  77. * dst_img - obraz, do ktereho zaznamename vyplneni
  78. * value - hodnota, pro kterou provedeme vyplneni
  79. */
  80. void fill_step(IplImage *src_img, IplImage *dst_img, IplImage *height_img, const int x, const int y, const uchar value, Building *building) {
  81.     int width, height;
  82.     int z;
  83.  
  84. } //fill_step
  85.  
  86.  
  87. /**
  88. * Provede flood fill ze zadaneho bodu (x, y). Funkce si zapamatuje hodnotu na souradnici (x, y)
  89. * a vyplnuje okoli pomoci funkce fill_step tak dlouho, dokud je hodnota v okolnich bodech stejna.
  90. * Vyplnovani provadejte na nejakem docasnem obraze, aby nedoslo k poskozeni puvodniho obrazu.
  91. * src_img - obraz na kterem se bude provadet vyplnovani
  92. * dst_img - obraz, do ktereho zaznamename vyplneni
  93. */
  94. void flood_fill(IplImage *src_img, IplImage *dst_img, IplImage *height_img, const int x, const int y) {
  95.     int width, height;
  96.     IplImage *tmp_ff_img;
  97.  
  98. } //flood_fill
  99.  
  100.  
  101. void make_binary_file(const char *input_filename, const char *out_filename) {
  102.     FILE *f_in, *f_out;
  103.     char line[LINE_SIZE];
  104.     char *no = NULL;
  105.     long line_no = 0;
  106.     float x, y, z;
  107.  
  108.     f_in = fopen(input_filename, "r");
  109.     f_out = fopen(out_filename, "wb");
  110.  
  111.     while (fgets(line, LINE_SIZE, f_in) != NULL) {
  112.         if (line_no % 1000000 == 0) {
  113.             printf("Processing line: %ld Million\n", line_no / 1000000);
  114.         }
  115.  
  116.         no = (char*)strtok(line, " ");
  117.         SKIP_LINE(no);
  118.         no = (char*)strtok(NULL, " ");
  119.         SKIP_LINE(no);
  120.         no = (char*)strtok(NULL, " ");
  121.         SKIP_LINE(no);
  122.         no = (char*)strtok(NULL, " ");
  123.         SKIP_LINE(no);
  124.         no = (char*)strtok(NULL, " ");
  125.         SKIP_LINE(no);
  126.         x = (float)atof(no);
  127.         no = (char*)strtok(NULL, " ");
  128.         SKIP_LINE(no)
  129.             y = (float)atof(no);
  130.         no = (char*)strtok(NULL, " ");
  131.         SKIP_LINE(no);
  132.         z = (float)atof(no);
  133.  
  134.         fwrite(&x, sizeof(x), 1, f_out);
  135.         fwrite(&y, sizeof(y), 1, f_out);
  136.         fwrite(&z, sizeof(z), 1, f_out);
  137.  
  138.         line_no++;
  139.     }
  140.  
  141.     printf("Closing file: %s\n", input_filename);
  142.     printf("Closing file: %s\n", out_filename);
  143.     fclose(f_in);
  144.     fclose(f_out);
  145. } //make_binary_file
  146.  
  147.  
  148. /**
  149. * Zjisti minimalni a maximalni souradnice v zadanem souboru.
  150. * Nezapomente, ze soubor tvori S-JTSK souradnice.
  151. */
  152. void get_min_max(const char *filename, float *a_min_x, float *a_max_x, float *a_min_y, float *a_max_y, float *a_min_z, float *a_max_z) {
  153.     FILE *f = NULL;
  154.     float x, y, z;
  155.     float min_x, min_y, min_z, max_x, max_y, max_z;
  156.     int l_type;
  157.  
  158.     f = fopen(filename, "r");
  159.  
  160.     min_x = min_y = min_z = FLT_MAX;
  161.  
  162.     max_x = max_y = max_z = -FLT_MAX;
  163.  
  164.     while (!feof(f)){
  165.         fread(&x, sizeof(x), 1, f);
  166.         fread(&y, sizeof(y), 1, f);
  167.         fread(&z, sizeof(z), 1, f);
  168.         fread(&l_type, sizeof(l_type), 1, f);
  169.  
  170.         if (x<min_x){
  171.             min_x = x;
  172.         }
  173.         else if (x>max_x){
  174.             max_x = x;
  175.         }
  176.  
  177.         if (y<min_y){
  178.             min_y = y;
  179.         }
  180.         else if (y>max_y){
  181.             max_y = y;
  182.         }
  183.  
  184.         if (z<min_z){
  185.             min_z = z;
  186.         }
  187.         else if (z>max_z){
  188.             max_z = z;
  189.         }
  190.     }
  191.  
  192.     fclose(f);
  193.  
  194.     *a_min_x = min_x;
  195.     *a_max_x = max_x;
  196.     *a_min_y = min_y;
  197.     *a_max_y = max_y;
  198.     *a_min_z = min_z;
  199.     *a_max_z = max_z;
  200. } //get_min_max
  201.  
  202.  
  203. /**
  204. * Naplni obraz daty z lidaru.
  205. * Vsechny lidarove body jsou ukladany do pole, ktere ma rozmery obrazu. Pote je jednotlivym pixelum prirazena
  206. * hodnota jako prumer hodnot z odpovidajiciho prvku pole. Timto jednoduchym pristupem vsak dochazi ke ztrate dat.
  207. * filename - soubor s binarnimi daty
  208. * img - vystupni obrazek
  209. */
  210. void fill_image(const char *filename, IplImage *img, float min_x, float max_x, float min_y, float max_y, float min_z, float max_z) {
  211.     FILE *f = NULL;
  212.     int delta_x, delta_y, delta_z;
  213.     float fx, fy, fz;
  214.     int x, y, l_type;
  215.     int stride;
  216.     int num_points = 0;
  217.     float range = 0.0f;
  218.     float *avg = NULL;
  219.     int *avg_count = NULL;
  220.  
  221.     // naalokujeme pomocna pole, ve kterych budeme ukaladat hodnoty z lidaru
  222.     // a pocet techto hodnot pro kazdy pixel
  223.     avg = (float*)malloc(img->width*img->height*sizeof(float));//v tomto poli jsou hodnoty 'z' (hodnota nám říká jakou barvu bude mít bod) souřadnic na konkrétním bodu obrázku na pozici xy
  224.     avg_count = (int*)malloc(img->width*img->height*sizeof(int));//hodnoty je potřeba průměrovat, toto pole je pouze na zápis počtu...
  225.  
  226.     f = fopen(filename, "r");
  227.  
  228.     //nulování pole
  229.     for (int i = 0; i<img->width*img->height; i++){
  230.         avg[i] = 0.0f;
  231.         avg_count[i] = 0;
  232.     }
  233.  
  234.     // projdeme soubor a hodnoty priradime do poli
  235.     while (!feof(f)){
  236.         fread(&fx, sizeof(fx), 1, f);
  237.         fread(&fy, sizeof(fy), 1, f);
  238.         fread(&fz, sizeof(fz), 1, f);
  239.         fread(&l_type, sizeof(l_type), 1, f);
  240.  
  241.         fx -= min_x;//odečteme minimální hodnotu x abychom dostali ze souřadnic které jsou mimo indexy pole indexy 0-img->width
  242.         fy -= min_y;//odečteme minimální hodnotu y abychom dostali ze souřadnic které jsou mimo indexy pole indexy 0-img->height
  243.  
  244.         x = cvRound(fx);//vratí přetypovanou hodnotu z původního float do int-kvůli indexaci pole
  245.         y = cvRound(fy);
  246.  
  247.         if (x < img->width && y < img->height)//z nějakýho neznámýho důvodu mě to na konci čtení vyhodilo jako indexy strašný hausnumera, pokud to bude chodit bez toho tak to smažte...
  248.         {
  249.             avg[x + y*img->width] += fz;//přičte přečtenou hodnotu souřadnice z
  250.             avg_count[x + y*img->width]++;//inkrementuje počet pro pozdější výpočet průměru
  251.         }
  252.     }
  253.  
  254.     fclose(f);
  255.  
  256.     range = 255 / (max_z - min_z);//normalizace hodnot souřadnice z, které jsou ve zdrojovém souboru od hodnoty cca 220 do hodnoty 260, cílová hodnota musí být v rozmezí 0-255, pokud bychom jenom odečetli konstantu tak by byl obrázek málo kontrastní
  257.  
  258.     //přepočet zetové souřadnice
  259.     for (int i = 0; i<img->width*img->height; i++){
  260.         avg[i] /= avg_count[i];//výpočet průměru
  261.         avg[i] -= min_z;//odečtení minima tím dostaneme hodnotu v rozmezí 0-40
  262.         avg[i] *= range;//přepočet na hodnoty 0-255
  263.     }
  264.  
  265.     // hodnoty z pomocneho pole priradime do obrazu
  266.     for (y = 0; y < img->height; y++) {
  267.         for (x = 0; x < img->width; x++) {
  268.             CV_IMAGE_ELEM(img, uchar, y, x) = (uchar)avg[x + y*img->width];//vyplní jednotlivé body do obrázku
  269.         }
  270.     }
  271.  
  272. } //fill_image
  273.  
  274.  
  275. void make_edges(const IplImage *src_img, IplImage *sobel_img) {
  276.     cvCanny(src_img, sobel_img, 1, 80);
  277. }
  278.  
  279. /**
  280. * Prevede hodnoty obrazu na pouze 2 hodnoty. Hranici mozno nastavit experimentalne.
  281. */
  282. void binarize_image(IplImage *img) {
  283.     int x, y;
  284.     uchar value;
  285.  
  286. }
  287.  
  288.  
  289. void process_lidar(const char *txt_file, const char *bin_file, const char *img_file) {
  290.     float min_x, max_x, min_y, max_y, min_z, max_z;
  291.     float delta_x, delta_y, delta_z;
  292.     MouseProbe *probe;
  293.  
  294.     IplImage *img = NULL;      // obraz pro vstup lidarovych dat
  295.     IplImage *show_img = NULL; // obraz pro kresleni nalezenych ploch
  296.     IplImage *edge_img = NULL; // obraz pro hrany
  297.  
  298.     probe = (MouseProbe*)malloc(sizeof(probe[0]));
  299.  
  300.     //make_binary_file( txt_file, bin_file );
  301.     get_min_max(bin_file, &min_x, &max_x, &min_y, &max_y, &min_z, &max_z);
  302.  
  303.     printf("min x: %f, max x: %f\n", min_x, max_x);
  304.     printf("min y: %f, max y: %f\n", min_y, max_y);
  305.     printf("min z: %f, max z: %f\n", min_z, max_z);
  306.  
  307.     delta_x = max_x - min_x;
  308.     delta_y = max_y - min_y;
  309.     delta_z = max_z - min_z;
  310.  
  311.     printf("delta x: %f\n", delta_x);
  312.     printf("delta y: %f\n", delta_y);
  313.     printf("delta z: %f\n", delta_z);
  314.  
  315.     // vytvorime obrazky podle informari ze souboru
  316.     img = cvCreateImage(cvSize(cvRound(delta_x + 0.5f), cvRound(delta_y + 0.5f)), IPL_DEPTH_8U, 1);
  317.     show_img = cvCreateImage(cvSize(cvRound(delta_x + 0.5f), cvRound(delta_y + 0.5f)), IPL_DEPTH_8U, 3);
  318.     edge_img = cvCreateImage(cvSize(cvRound(delta_x + 0.5f), cvRound(delta_y + 0.5f)), IPL_DEPTH_8U, 1);
  319.  
  320.     create_windows(img->width, img->height);
  321.  
  322.     cvSetMouseCallback(STEP1_WIN_NAME, mouse_probe_handler, probe);
  323.     cvSetMouseCallback(STEP2_WIN_NAME, mouse_probe_handler, probe);
  324.     probe->img = img;
  325.     probe->show_img = show_img;
  326.     probe->edge_img = edge_img;
  327.  
  328.  
  329.     printf("Image w=%d, h=%d\n", img->width, img->height);
  330.  
  331.     // naplnime vstupni obraz daty z lidaru
  332.     fill_image(bin_file, img, min_x, max_x, min_y, max_y, min_z, max_z);
  333.     cvCvtColor(img, show_img, CV_GRAY2RGB);
  334.  
  335.     // vytvorime obraz hran
  336.     //make_edges( img, edge_img );
  337.  
  338.     // muzeme obraz hran binarizovat, ale v prvni fazi to neni nutne
  339.     //binarize_image( edge_img );
  340.     // dilatace, eroze
  341.  
  342.     // v cyklu cekame na odezvu uzivatele (klikani uzivatele)
  343.     // pokud zmackneme klavesu 'q', program konci
  344.  
  345.     while (1) {
  346.         cvShowImage(STEP1_WIN_NAME, show_img);
  347.         //cvShowImage( STEP2_WIN_NAME, edge_img );
  348.         //cvSaveImage( img_file, img );
  349.         int key = cvWaitKey(10);
  350.         if (key == 'q') {
  351.             break;
  352.         }
  353.     }
  354.  
  355.  
  356.     cvDestroyWindow(STEP1_WIN_NAME);
  357.     cvDestroyWindow(STEP2_WIN_NAME);
  358.  
  359.     cvReleaseImage(&img);
  360.     cvReleaseImage(&show_img);
  361.     cvReleaseImage(&edge_img);
  362. }
  363.  
  364.  
  365. int main(int argc, char *argv[]) {
  366.     char *txt_file, *bin_file, *img_file;
  367.  
  368.     if (argc < 4) {
  369.         printf("Not enough parameters.\n");
  370.         exit(1);
  371.     }
  372.  
  373.     txt_file = argv[1];
  374.     bin_file = argv[2];
  375.     img_file = argv[3];
  376.  
  377.     process_lidar(txt_file, bin_file, img_file);
  378.  
  379.     return 0;
  380. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement