home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_09_11 / 9n11088a < prev    next >
Text File  |  1991-04-13  |  17KB  |  734 lines

  1.  
  2.        /***********************************************
  3.        *
  4.        *       file d:\cips\edge.c
  5.        *
  6.        *       Functions: This file contains
  7.        *          detect_edges
  8.        *          setup_masks
  9.        *          get_edge_options
  10.        *          perform_convolution
  11.        *          quick_edge
  12.        *          fix_edges
  13.        *
  14.        *       Purpose:
  15.        *          These functions implement several
  16.        *          types of basic edge detection.
  17.        *
  18.        *       External Calls:
  19.        *          wtiff.c - does_not_exist
  20.        *                    round_off_image_size
  21.        *                    create_allocate_tiff_file
  22.        *                    write_array_into_tiff_image
  23.        *          tiff.c - read_tiff_header
  24.        *          rtiff.c - read_tiff_image
  25.        *          numcvrt.c - get_integer
  26.        *
  27.        *
  28.        *       Modifications:
  29.        *          27 January 1991 - created
  30.        *
  31.        *************************************************/
  32.  
  33. #include "d:\cips\cips.h"
  34.  
  35.  
  36.  
  37.  
  38.  
  39. short quick_mask[3][3] =  {
  40.        {-1,  0, -1},
  41.        { 0,  4,  0},
  42.        {-1,  0, -1} };
  43.  
  44.  
  45.    /***************************
  46.    *
  47.    *   Directions for the masks
  48.    *  3 2 1
  49.    *  4 x 0
  50.    *  5 6 7
  51.    *
  52.    ****************************/
  53.  
  54.    /* masks for kirsch operator */
  55. short kirsch_mask_0[3][3] =  {
  56.        { 5,  5,  5},
  57.        {-3,  0, -3},
  58.        {-3, -3, -3} };
  59.  
  60. short kirsch_mask_1[3][3] =  {
  61.        {-3,  5,  5},
  62.        {-3,  0,  5},
  63.        {-3, -3, -3} };
  64.  
  65. short kirsch_mask_2[3][3] =  {
  66.        {-3, -3,  5},
  67.        {-3,  0,  5},
  68.        {-3, -3,  5} };
  69.  
  70. short kirsch_mask_3[3][3] =  {
  71.        {-3, -3, -3},
  72.        {-3,  0,  5},
  73.        {-3,  5,  5} };
  74.  
  75. short kirsch_mask_4[3][3] =  {
  76.        {-3, -3, -3},
  77.        {-3,  0, -3},
  78.        { 5,  5,  5} };
  79.  
  80. short kirsch_mask_5[3][3] =  {
  81.        {-3, -3, -3},
  82.        { 5,  0, -3},
  83.        { 5,  5, -3} };
  84.  
  85. short kirsch_mask_6[3][3] =  {
  86.        { 5, -3, -3},
  87.        { 5,  0, -3},
  88.        { 5, -3, -3} };
  89.  
  90. short kirsch_mask_7[3][3] =  {
  91.        { 5,  5, -3},
  92.        { 5,  0, -3},
  93.        {-3, -3, -3} };
  94.  
  95.  
  96.  
  97.  
  98.  
  99.  
  100.    /* masks for prewitt operator */
  101.  
  102. short prewitt_mask_0[3][3] =  {
  103.        { 1,  1,  1},
  104.        { 1, -2,  1},
  105.        {-1, -1, -1} };
  106.  
  107. short prewitt_mask_1[3][3] =  {
  108.        { 1,  1,  1},
  109.        { 1, -2, -1},
  110.        { 1, -1, -1} };
  111.  
  112. short prewitt_mask_2[3][3] =  {
  113.        { 1,  1, -1},
  114.        { 1, -2, -1},
  115.        { 1,  1, -1} };
  116.  
  117. short prewitt_mask_3[3][3] =  {
  118.        { 1, -1, -1},
  119.        { 1, -2, -1},
  120.        { 1,  1,  1} };
  121.  
  122. short prewitt_mask_4[3][3] =  {
  123.        {-1, -1, -1},
  124.        { 1, -2,  1},
  125.        { 1,  1,  1} };
  126.  
  127. short prewitt_mask_5[3][3] =  {
  128.        {-1, -1,  1},
  129.        {-1, -2,  1},
  130.        { 1,  1,  1} };
  131.  
  132. short prewitt_mask_6[3][3] =  {
  133.        {-1,  1,  1},
  134.        {-1, -2,  1},
  135.        {-1,  1,  1} };
  136.  
  137. short prewitt_mask_7[3][3] =  {
  138.        { 1,  1,  1},
  139.        {-1, -2,  1},
  140.        {-1, -1,  1} };
  141.  
  142.  
  143.  
  144.  
  145.  
  146.  
  147.    /* masks for sobel operator */
  148.  
  149. short sobel_mask_0[3][3] =  {
  150.        { 1,  2,  1},
  151.        { 0,  0,  0},
  152.        {-1, -2, -1} };
  153.  
  154. short sobel_mask_1[3][3] =  {
  155.        { 2,  1,  0},
  156.        { 1,  0, -1},
  157.        { 0, -1, -2} };
  158.  
  159. short sobel_mask_2[3][3] =  {
  160.        { 1,  0, -1},
  161.        { 2,  0, -2},
  162.        { 1,  0, -1} };
  163. short sobel_mask_3[3][3] =  {
  164.        { 0, -1, -2},
  165.        { 1,  0, -1},
  166.        { 2,  1,  0} };
  167.  
  168. short sobel_mask_4[3][3] =  {
  169.        {-1, -2, -1},
  170.        { 0,  0,  0},
  171.        { 1,  2,  1} };
  172.  
  173. short sobel_mask_5[3][3] =  {
  174.        {-2, -1,  0},
  175.        {-1,  0,  1},
  176.        { 0,  1,  2} };
  177.  
  178. short sobel_mask_6[3][3] =  {
  179.        {-1,  0,  1},
  180.        {-2,  0,  2},
  181.        {-1,  0,  1} };
  182.  
  183. short sobel_mask_7[3][3] =  {
  184.        { 0,  1,  2},
  185.        {-1,  0,  1},
  186.        {-2, -1,  0} };
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193.   /**************************************************
  194.   *
  195.   *   detect_edges(...
  196.   *
  197.   *   This function detects edges in an area of one
  198.   *   image and sends the result to another image
  199.   *   on disk.  It reads the input image from disk,
  200.   *   calls a convolution function, and then writes
  201.   *   the result out to disk.  If needed, it
  202.   *   allocates space on disk for the output image.
  203.   *
  204.   ***************************************************/
  205.  
  206.  
  207.  
  208.  
  209. detect_edges(in_name, out_name, the_image, out_image,
  210.              il, ie, ll, le, detect_type, threshold,
  211.              high)
  212.    char   in_name[], out_name[];
  213.    int    detect_type, high, il, ie,
  214.           ll, le, threshold;
  215.    short  the_image[ROWS][COLS], out_image[ROWS][COLS];
  216.  
  217. {
  218.    int    i, j, k, length, width;
  219.    struct tiff_header_struct image_header;
  220.  
  221.  
  222.    if(does_not_exist(out_name)){
  223.       read_tiff_header(in_name, &image_header);
  224.       round_off_image_size(&image_header,
  225.                            &length, &width);
  226.       image_header.image_length = length*ROWS;
  227.       image_header.image_width  = width*COLS;
  228.       create_allocate_tiff_file(out_name, &image_header,
  229.                                 out_image);
  230.    }  /* ends if does_not_exist */
  231.  
  232.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  233.  
  234.    read_tiff_header(in_name, &image_header);
  235.  
  236.    perform_convolution(the_image, out_image,
  237.                        detect_type, threshold,
  238.                        &image_header, high);
  239.  
  240.    fix_edges(out_image, 1);
  241.  
  242.    write_array_into_tiff_image(out_name, out_image,
  243.                                il, ie, ll, le);
  244. }  /* ends detect_edges */
  245.  
  246.  
  247.  
  248.  
  249.  
  250.  
  251.  
  252.      /**********************************************************
  253.      *
  254.      *   perform_convolution(...
  255.      *
  256.      *   This function performs convolution between the input
  257.      *   image and 8 3x3 masks.  The result is placed in
  258.      *   the out_image.
  259.      *
  260.      ********************************************************/
  261.  
  262. perform_convolution(image, out_image,
  263.                     detect_type, threshold,
  264.                     image_header, high)
  265.    short image[ROWS][COLS],
  266.          out_image[ROWS][COLS];
  267.    int   detect_type, high, threshold;
  268.    struct tiff_header_struct *image_header;
  269. {
  270.  
  271.    int a,
  272.        b,
  273.        i,
  274.        is_present,
  275.        j,
  276.        sum;
  277.  
  278.    short  mask_0[3][3],
  279.           mask_1[3][3],
  280.           mask_2[3][3],
  281.           mask_3[3][3],
  282.           mask_4[3][3],
  283.           mask_5[3][3],
  284.           mask_6[3][3],
  285.           mask_7[3][3],
  286.           max,
  287.           min,
  288.           new_hi,
  289.           new_low;
  290.  
  291.  
  292.    setup_masks(detect_type, mask_0, mask_1,
  293.                mask_2, mask_3, mask_4, mask_5,
  294.                mask_6, mask_7);
  295.  
  296.    new_hi  = 250;
  297.    new_low = 16;
  298.    if(image_header->bits_per_pixel == 4){
  299.        new_hi  = 10;
  300.        new_low = 3;
  301.    }
  302.  
  303.    min = 0;
  304.    max = 255;
  305.    if(image_header->bits_per_pixel == 4)
  306.       max = 16;
  307.  
  308.      /* clear output image array */
  309.    for(i=0; i<ROWS; i++)
  310.       for(j=0; j<COLS; j++)
  311.          out_image[i][j] = 0;
  312.  
  313.    printf("\n ");
  314.  
  315.    for(i=1; i<ROWS-1; i++){
  316.       if( (i%10) == 0) printf("%3d", i);
  317.       for(j=1; j<COLS-1; j++){
  318.  
  319.  
  320.          /* Convolve for all 8 directions */
  321.  
  322.          /* 0 direction */
  323.  
  324.       sum = 0;
  325.       for(a=-1; a<2; a++){
  326.          for(b=-1; b<2; b++){
  327.             sum = sum + image[i+a][j+b] *
  328.                   mask_0[a+1][b+1];
  329.          }
  330.       }
  331.          if(sum > max) sum = max;
  332.          if(sum < 0)   sum = 0;
  333.       out_image[i][j]   = sum;
  334.  
  335.  
  336.          /* 1 direction */
  337.  
  338.       sum = 0;
  339.       for(a=-1; a<2; a++){
  340.          for(b=-1; b<2; b++){
  341.             sum = sum + image[i+a][j+b] * mask_1[a+1][b+1];
  342.          }
  343.       }
  344.          if(sum > max) sum = max;
  345.          if(sum < 0)   sum = 0;
  346.       out_image[i][j]   = sum;
  347.  
  348.  
  349.          /* 2 direction */
  350.  
  351.       sum = 0;
  352.       for(a=-1; a<2; a++){
  353.          for(b=-1; b<2; b++){
  354.             sum = sum + image[i+a][j+b] * mask_2[a+1][b+1];
  355.          }
  356.       }
  357.          if(sum > max) sum = max;
  358.          if(sum < 0)   sum = 0;
  359.       out_image[i][j]   = sum;
  360.  
  361.  
  362.          /* 3 direction */
  363.  
  364.       sum = 0;
  365.       for(a=-1; a<2; a++){
  366.          for(b=-1; b<2; b++){
  367.             sum = sum + image[i+a][j+b] * mask_3[a+1][b+1];
  368.          }
  369.       }
  370.          if(sum > max) sum = max;
  371.          if(sum < 0)   sum = 0;
  372.       out_image[i][j]   = sum;
  373.  
  374.  
  375.          /* 4 direction */
  376.  
  377.       sum = 0;
  378.       for(a=-1; a<2; a++){
  379.          for(b=-1; b<2; b++){
  380.             sum = sum + image[i+a][j+b] * mask_4[a+1][b+1];
  381.          }
  382.       }
  383.          if(sum > max) sum = max;
  384.          if(sum < 0)   sum = 0;
  385.       out_image[i][j]   = sum;
  386.  
  387.  
  388.          /* 5 direction */
  389.  
  390.       sum = 0;
  391.       for(a=-1; a<2; a++){
  392.          for(b=-1; b<2; b++){
  393.             sum = sum + image[i+a][j+b] * mask_5[a+1][b+1];
  394.          }
  395.       }
  396.          if(sum > max) sum = max;
  397.          if(sum < 0)   sum = 0;
  398.       out_image[i][j]   = sum;
  399.  
  400.  
  401.          /* 6 direction */
  402.       sum = 0;
  403.       for(a=-1; a<2; a++){
  404.          for(b=-1; b<2; b++){
  405.             sum = sum + image[i+a][j+b] * mask_6[a+1][b+1];
  406.          }
  407.       }
  408.          if(sum > max) sum = max;
  409.          if(sum < 0)   sum = 0;
  410.       out_image[i][j]   = sum;
  411.  
  412.  
  413.          /* 7 direction */
  414.  
  415.       sum = 0;
  416.       for(a=-1; a<2; a++){
  417.          for(b=-1; b<2; b++){
  418.             sum = sum + image[i+a][j+b] * mask_7[a+1][b+1];
  419.          }
  420.       }
  421.          if(sum > max) sum = max;
  422.          if(sum < 0)   sum = 0;
  423.       out_image[i][j]   = sum;
  424.  
  425.  
  426.       }  /* ends loop over j */
  427.    }  /* ends loop over i */
  428.  
  429.  
  430.      /* if desired, threshold the output image */
  431.    if(threshold == 1){
  432.        for(i=0; i<ROWS; i++){
  433.           for(j=0; j<COLS; j++){
  434.              if(out_image[i][j] > high){
  435.                   out_image[i][j] = new_hi;
  436.              }
  437.              else{
  438.                   out_image[i][j] = new_low;
  439.              }
  440.           }
  441.        }
  442.    }  /* ends if threshold == 1 */
  443.  
  444. }  /* ends perform_convolution */
  445.  
  446.  
  447.  
  448.  
  449.  
  450.  
  451.  
  452.      /*******************************************
  453.      *
  454.      *   quick_edge(...
  455.      *
  456.      *   This function finds edges by using
  457.      *   a single 3x3 mask.
  458.      *
  459.      *******************************************/
  460.  
  461.  
  462. quick_edge(in_name, out_name, the_image, out_image,
  463.              il, ie, ll, le, threshold, high)
  464.    char   in_name[], out_name[];
  465.    int    high, il, ie, ll, le, threshold;
  466.    short  the_image[ROWS][COLS], out_image[ROWS][COLS];
  467.  
  468. {
  469.    int    a, b, i, j, k,
  470.           length, max, new_hi, new_low,
  471.           sum, width;
  472.    struct tiff_header_struct image_header;
  473.  
  474.  
  475.    if(does_not_exist(out_name)){
  476.       printf("\n\n output file does not exist %s", out_name);
  477.       read_tiff_header(in_name, &image_header);
  478.       round_off_image_size(&image_header,
  479.                            &length, &width);
  480.       image_header.image_length = length*ROWS;
  481.       image_header.image_width  = width*COLS;
  482.       create_allocate_tiff_file(out_name, &image_header,
  483.                                 out_image);
  484.    }  /* ends if does_not_exist */
  485.  
  486.    read_tiff_header(in_name, &image_header);
  487.    new_hi  = 250;
  488.    new_low = 16;
  489.    if(image_header.bits_per_pixel == 4){
  490.        new_hi  = 10;
  491.        new_low = 3;
  492.    }
  493.  
  494.    max = 255;
  495.    if(image_header.bits_per_pixel == 4)
  496.       max = 16;
  497.  
  498.  
  499.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  500.  
  501.          /* Do convolution over image array */
  502.    printf("\n");
  503.    for(i=1; i<ROWS-1; i++){
  504.       if( (i%10) == 0) printf("%d ", i);
  505.       for(j=1; j<COLS-1; j++){
  506.          sum = 0;
  507.          for(a=-1; a<2; a++){
  508.             for(b=-1; b<2; b++){
  509.                sum = sum +
  510.                      the_image[i+a][j+b] *
  511.                      quick_mask[a+1][b+1];
  512.             }
  513.          }
  514.          if(sum < 0)   sum = 0;
  515.          if(sum > max) sum = max;
  516.          out_image[i][j]   = sum;
  517.  
  518.       }  /* ends loop over j */
  519.    }  /* ends loop over i */
  520.  
  521.      /* if desired, threshold the output image */
  522.    if(threshold == 1){
  523.        for(i=0; i<ROWS; i++){
  524.           for(j=0; j<COLS; j++){
  525.              if(out_image[i][j] > high){
  526.                   out_image[i][j] = new_hi;
  527.              }
  528.              else{
  529.                   out_image[i][j] = new_low;
  530.              }
  531.           }
  532.        }
  533.    }  /* ends if threshold == 1 */
  534.  
  535.    fix_edges(out_image, 1);
  536.  
  537.    write_array_into_tiff_image(out_name, out_image,
  538.                                il, ie, ll, le);
  539.  
  540. }  /* ends quick_edge */
  541.  
  542.  
  543.  
  544.  
  545.  
  546.  
  547.  
  548.  
  549.    /***********************************************
  550.     *
  551.     *    setup_masks(...
  552.     *
  553.     *    This function copies the mask values defined
  554.     *    at the top of this file into the mask
  555.     *    arrays mask_0 through mask_7.
  556.     *
  557.     ***********************************************/
  558.  
  559.  
  560.  
  561. setup_masks(detect_type, mask_0, mask_1, mask_2, mask_3,
  562.             mask_4, mask_5, mask_6, mask_7)
  563.    int    detect_type;
  564.    short  mask_0[3][3],
  565.           mask_1[3][3],
  566.           mask_2[3][3],
  567.           mask_3[3][3],
  568.           mask_4[3][3],
  569.           mask_5[3][3],
  570.           mask_6[3][3],
  571.           mask_7[3][3];
  572. {
  573.    int i, j;
  574.  
  575.    if(detect_type == KIRSCH){
  576.       for(i=0; i<3; i++){
  577.         for(j=0; j<3; j++){
  578.           mask_0[i][j] = kirsch_mask_0[i][j];
  579.           mask_1[i][j] = kirsch_mask_1[i][j];
  580.           mask_2[i][j] = kirsch_mask_2[i][j];
  581.           mask_3[i][j] = kirsch_mask_3[i][j];
  582.           mask_4[i][j] = kirsch_mask_4[i][j];
  583.           mask_5[i][j] = kirsch_mask_5[i][j];
  584.           mask_6[i][j] = kirsch_mask_6[i][j];
  585.           mask_7[i][j] = kirsch_mask_7[i][j];
  586.         }
  587.       }
  588.    }  /* ends if detect_type == KIRSCH */
  589.  
  590.  
  591.    if(detect_type == PREWITT){
  592.       for(i=0; i<3; i++){
  593.         for(j=0; j<3; j++){
  594.           mask_0[i][j] = prewitt_mask_0[i][j];
  595.           mask_1[i][j] = prewitt_mask_1[i][j];
  596.           mask_2[i][j] = prewitt_mask_2[i][j];
  597.           mask_3[i][j] = prewitt_mask_3[i][j];
  598.           mask_4[i][j] = prewitt_mask_4[i][j];
  599.           mask_5[i][j] = prewitt_mask_5[i][j];
  600.           mask_6[i][j] = prewitt_mask_6[i][j];
  601.           mask_7[i][j] = prewitt_mask_7[i][j];
  602.         }
  603.       }
  604.    }  /* ends if detect_type == PREWITT */
  605.  
  606.  
  607.    if(detect_type == SOBEL){
  608.       for(i=0; i<3; i++){
  609.         for(j=0; j<3; j++){
  610.           mask_0[i][j] = sobel_mask_0[i][j];
  611.           mask_1[i][j] = sobel_mask_1[i][j];
  612.           mask_2[i][j] = sobel_mask_2[i][j];
  613.           mask_3[i][j] = sobel_mask_3[i][j];
  614.           mask_4[i][j] = sobel_mask_4[i][j];
  615.           mask_5[i][j] = sobel_mask_5[i][j];
  616.           mask_6[i][j] = sobel_mask_6[i][j];
  617.           mask_7[i][j] = sobel_mask_7[i][j];
  618.         }
  619.       }
  620.    }  /* ends if detect_type == SOBEL */
  621.  
  622.  
  623.  
  624. }  /* ends setup_masks */
  625.  
  626.  
  627.  
  628.    /***********************************************
  629.     *
  630.     *    get_edge_options(...
  631.     *
  632.     *    This function queries the user for the
  633.     *    parameters need to perform edge
  634.     *    detection.
  635.     *
  636.     ***********************************************/
  637.  
  638.  
  639. get_edge_options(detect_type, threshold, high)
  640.     int *detect_type, *high, *threshold;
  641. {
  642.     int not_finished, response;
  643.     not_finished = 1;
  644.     while(not_finished){
  645.  
  646.       printf("\nThe Edge Detector options are:\n");
  647.       printf("\n\t1.  Type of edge detector is %d", *detect_type);
  648.       printf("\n\t      (recall 1=Prewitt 2=Kirsch 3=Sobel
  649. 4=quick)");
  650.       printf("\n\t2.  Threshold output is %d (0=off 1=on)",
  651. *threshold);
  652.       printf("\n\t3.  High threshold is %d", *high);
  653.       printf("\n\nEnter choice (0 = no change) _\b");
  654.  
  655.  
  656.       get_integer(&response);
  657.  
  658.       if(response == 0){
  659.         not_finished = 0;
  660.       }
  661.  
  662.  
  663.       if(response == 1){
  664.         printf("\n\nEnter type of edge detector");
  665.         printf("\n   (recall 1=Prewitt 2=Kirsch 3=Sobel 4=quick)");
  666.         printf("\n  _\b");
  667.         get_integer(detect_type);
  668.       }
  669.  
  670.       if(response == 2){
  671.         printf("\n\nEnter threshold output (0=off 1=on)");
  672.         printf("\n  _\b");
  673.         get_integer(threshold);
  674.       }
  675.  
  676.       if(response == 3){
  677.         printf("\n\nEnter high threshold");
  678.         printf("\n  _\b");
  679.         get_integer(high);
  680.       }
  681.  
  682.     }  /* ends while not_finished */
  683.  
  684. }  /* ends get_edge_options */
  685.  
  686.  
  687.  
  688.  
  689.  
  690.  
  691.    /***********************************************
  692.     *
  693.     *    fix_edges(...
  694.     *
  695.     *    This function fixes the edges of an image
  696.     *    array after convolution was performed.
  697.     *    It copies the points near the edge of the
  698.     *    array out to the edge of the array.
  699.     *
  700.     ***********************************************/
  701.  
  702.  
  703.  
  704. fix_edges(im, w)
  705.       int   w;
  706.       short im[ROWS][COLS];
  707. {
  708.    int i, j;
  709.  
  710.  
  711.       /* four corners */
  712.    for(i=w; i>0; i--){
  713.     im[i-1][i-1] = im[i][i];
  714.     im[i-1][COLS-(i-1)] = im[i][COLS-1-(i-1)];
  715.     im[ROWS-(i-1)][i-1] = im[ROWS-1-(i-1)][i];
  716.     im[ROWS-(i-1)][COLS-(i-1)] = im[ROWS-1-(i-1)][COLS-1-(i-1)];
  717.    }  /* ends four corners loop */
  718.  
  719.    for(i=0; i<ROWS; i++){
  720.       for(j=w; j>0; j--){
  721.        im[i][j-1] = im[i][j];
  722.        im[i][COLS-j] = im[i][COLS-j-1];
  723.       }
  724.    }
  725.  
  726.    for(j=0; j<COLS; j++){
  727.       for(i=w; i>0; i--){
  728.        im[i-1][j] = im[i][j];
  729.        im[ROWS-i][j] = im[ROWS-i-1][j];
  730.       }
  731.    }
  732.  
  733. }  /* ends fix_edges */
  734.