text: /*====================================================================*
   -  Copyright (C) 2001 Leptonica.  All rights reserved.
   -
   -  Redistribution and use in source and binary forms, with or without
   -  modification, are permitted provided that the following conditions
   -  are met:
   -  1. Redistributions of source code must retain the above copyright
   -     notice, this list of conditions and the following disclaimer.
   -  2. Redistributions in binary form must reproduce the above
   -     copyright notice, this list of conditions and the following
   -     disclaimer in the documentation and/or other materials
   -     provided with the distribution.
   -
   -  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   -  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   -  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
   -  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ANY
   -  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   -  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   -  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   -  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
   -  OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   -  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   -  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   *====================================================================*/
  
  /*
   * numa_reg2.c
   *
   *   Tests:
   *     * numa windowed stats
   *     * numa extraction from pix on a line
   *     * pixel averages and variances
   */
  
  #include <math.h>
  #ifndef  _WIN32
  #include <unistd.h>
  #else
  #include <windows.h>   /* for Sleep() */
  #endif  /* _WIN32 */
  #include "allheaders.h"
  
  #define   DO_ALL     1
  
  
  int main(int    argc,
           char **argv)
  {
  l_int32      i, j;
  l_int32      w, h, bw, bh, wpls, rval, gval, bval, same;
  l_uint32     pixel;
  l_uint32    *lines, *datas;
  l_float32    sum1, sum2, ave1, ave2, ave3, ave4, diff1, diff2;
  l_float32    var1, var2, var3;
  BOX         *box1, *box2;
  NUMA        *na, *na1, *na2, *na3, *na4;
  PIX         *pix, *pixs, *pix1, *pix2, *pix3, *pix4, *pix5, *pixg, *pixd;
  PIXA        *pixa;
  static char  mainName[] = "numa2_reg";
  
      if (argc != 1)
          return ERROR_INT(" Syntax:  numa2_reg", mainName, 1);
  
      lept_mkdir("lept");
  
      /* -------------------------------------------------------------------*
       *                         Numa-windowed stats                        *
       * -------------------------------------------------------------------*/
  #if  DO_ALL
      na = numaRead("lyra.5.na");
      numaWindowedStats(na, 5, &na1, &na2, &na3, &na4);
      gplotSimple1(na, GPLOT_PNG, "/tmp/lept/numa_lyra6", "Original");
      gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/numa_lyra7", "Mean");
      gplotSimple1(na2, GPLOT_PNG, "/tmp/lept/numa_lyra8", "Mean Square");
      gplotSimple1(na3, GPLOT_PNG, "/tmp/lept/numa_lyra9", "Variance");
      gplotSimple1(na4, GPLOT_PNG, "/tmp/lept/numa_lyra10", "RMS Difference");
  #ifndef  _WIN32
      sleep(1);
  #else
      Sleep(1000);
  #endif  /* _WIN32 */
      pixa = pixaCreate(5);
      pix1 = pixRead("/tmp/lept/numa_lyra6.png");
      pix2 = pixRead("/tmp/lept/numa_lyra7.png");
      pix3 = pixRead("/tmp/lept/numa_lyra8.png");
      pix4 = pixRead("/tmp/lept/numa_lyra9.png");
      pix5 = pixRead("/tmp/lept/numa_lyra10.png");
      pixSaveTiled(pix1, pixa, 1.0, 1, 25, 32);
      pixSaveTiled(pix2, pixa, 1.0, 1, 25, 32);
      pixSaveTiled(pix3, pixa, 1.0, 0, 25, 32);
      pixSaveTiled(pix4, pixa, 1.0, 1, 25, 32);
      pixSaveTiled(pix5, pixa, 1.0, 0, 25, 32);
      pixd = pixaDisplay(pixa, 0, 0);
      pixDisplay(pixd, 100, 100);
      pixWrite("/tmp/lept/numa_window.png", pixd, IFF_PNG);
      numaDestroy(&na);
      numaDestroy(&na1);
      numaDestroy(&na2);
      numaDestroy(&na3);
      numaDestroy(&na4);
      pixaDestroy(&pixa);
      pixDestroy(&pix1);
      pixDestroy(&pix2);
      pixDestroy(&pix3);
      pixDestroy(&pix4);
      pixDestroy(&pix5);
      pixDestroy(&pixd);
  #endif
  
      /* -------------------------------------------------------------------*
       *                        Extraction on a line                        *
       * -------------------------------------------------------------------*/
  #if  DO_ALL
          /* First, make a pretty image */
      w = h = 200;
      pixs = pixCreate(w, h, 32);
      wpls = pixGetWpl(pixs);
      datas = pixGetData(pixs);
      for (i = 0; i < 200; i++) {
          lines = datas + i * wpls;
          for (j = 0; j < 200; j++) {
              rval = (l_int32)((255. * j) / w + (255. * i) / h);
              gval = (l_int32)((255. * 2 * j) / w + (255. * 2 * i) / h) % 255;
              bval = (l_int32)((255. * 4 * j) / w + (255. * 4 * i) / h) % 255;
              composeRGBPixel(rval, gval, bval, &pixel);
              lines[j] = pixel;
          }
      }
      pixg = pixConvertTo8(pixs, 0);  /* and a grayscale version */
      pixWrite("/tmp/lept/numa_pixg.png", pixg, IFF_PNG);
      pixDisplay(pixg, 450, 100);
  
      na1 = pixExtractOnLine(pixg, 20, 20, 180, 20, 1);
      na2 = pixExtractOnLine(pixg, 40, 30, 40, 170, 1);
      na3 = pixExtractOnLine(pixg, 20, 170, 180, 30, 1);
      na4 = pixExtractOnLine(pixg, 20, 190, 180, 10, 1);
      gplotSimple1(na1, GPLOT_PNG, "/tmp/lept/numa_ext1", "Horizontal");
      gplotSimple1(na2, GPLOT_PNG, "/tmp/lept/numa_ext2", "Vertical");
      gplotSimple1(na3, GPLOT_PNG, "/tmp/lept/numa_ext3",
                  "Slightly more horizontal than vertical");
      gplotSimple1(na4, GPLOT_PNG, "/tmp/lept/numa_ext4",
                  "Slightly more vertical than horizontal");
  #ifndef  _WIN32
      sleep(1);
  #else
      Sleep(1000);
  #endif  /* _WIN32 */
      pixa = pixaCreate(4);
      pix1 = pixRead("/tmp/lept/numa_ext1.png");
      pix2 = pixRead("/tmp/lept/numa_ext2.png");
      pix3 = pixRead("/tmp/lept/numa_ext3.png");
      pix4 = pixRead("/tmp/lept/numa_ext4.png");
      pixSaveTiled(pix1, pixa, 1.0, 1, 25, 32);
      pixSaveTiled(pix2, pixa, 1.0, 0, 25, 32);
      pixSaveTiled(pix3, pixa, 1.0, 1, 25, 32);
      pixSaveTiled(pix4, pixa, 1.0, 0, 25, 32);
      pixd = pixaDisplay(pixa, 0, 0);
      pixDisplay(pixd, 100, 500);
      pixWrite("/tmp/lept/numa_extract.png", pixd, IFF_PNG);
      numaDestroy(&na1);
      numaDestroy(&na2);
      numaDestroy(&na3);
      numaDestroy(&na4);
      pixaDestroy(&pixa);
      pixDestroy(&pix1);
      pixDestroy(&pix2);
      pixDestroy(&pix3);
      pixDestroy(&pix4);
      pixDestroy(&pix5);
      pixDestroy(&pixs);
      pixDestroy(&pixg);
      pixDestroy(&pixd);
  #endif
  
      /* -------------------------------------------------------------------*
       *                     Row and column pixel sums                      *
       * -------------------------------------------------------------------*/
  #if  DO_ALL
          /* Sum by columns in two halves (left and right) */
      pixs = pixRead("test8.jpg");
      pixGetDimensions(pixs, &w, &h, NULL);
      box1 = boxCreate(0, 0, w / 2, h);
      box2 = boxCreate(w / 2, 0, w - 2 / 2, h);
      na1 = pixAverageByColumn(pixs, box1, L_BLACK_IS_MAX);
      na2 = pixAverageByColumn(pixs, box2, L_BLACK_IS_MAX);
      numaJoin(na1, na2, 0, -1);
      na3 = pixAverageByColumn(pixs, NULL, L_BLACK_IS_MAX);
      numaSimilar(na1, na3, 0.0, &same);
      if (same)
          fprintf(stderr, "Same for columns\n");
      else
          fprintf(stderr, "Error for columns\n");
      pix = pixConvertTo32(pixs);
      pixRenderPlotFromNumaGen(&pix, na3, L_HORIZONTAL_LINE, 3, h / 2, 80, 1,
                               0xff000000);
      pixRenderPlotFromNuma(&pix, na3, L_PLOT_AT_BOT, 3, 80, 0xff000000);
      boxDestroy(&box1);
      boxDestroy(&box2);
      numaDestroy(&na1);
      numaDestroy(&na2);
      numaDestroy(&na3);
  
          /* Sum by rows in two halves (top and bottom) */
      box1 = boxCreate(0, 0, w, h / 2);
      box2 = boxCreate(0, h / 2, w, h - h / 2);
      na1 = pixAverageByRow(pixs, box1, L_WHITE_IS_MAX);
      na2 = pixAverageByRow(pixs, box2, L_WHITE_IS_MAX);
      numaJoin(na1, na2, 0, -1);
      na3 = pixAverageByRow(pixs, NULL, L_WHITE_IS_MAX);
      numaSimilar(na1, na3, 0.0, &same);
      if (same)
          fprintf(stderr, "Same for rows\n");
      else
          fprintf(stderr, "Error for rows\n");
      pixRenderPlotFromNumaGen(&pix, na3, L_VERTICAL_LINE, 3, w / 2, 80, 1,
                               0x00ff0000);
      pixRenderPlotFromNuma(&pix, na3, L_PLOT_AT_RIGHT, 3, 80, 0x00ff0000);
      pixDisplay(pix, 500, 200);
      boxDestroy(&box1);
      boxDestroy(&box2);
      numaDestroy(&na1);
      numaDestroy(&na2);
      numaDestroy(&na3);
      pixDestroy(&pix);
  
          /* Average left by rows; right by columns; compare totals */
      box1 = boxCreate(0, 0, w / 2, h);
      box2 = boxCreate(w / 2, 0, w - 2 / 2, h);
      na1 = pixAverageByRow(pixs, box1, L_WHITE_IS_MAX);
      na2 = pixAverageByColumn(pixs, box2, L_WHITE_IS_MAX);
      numaGetSum(na1, &sum1);  /* sum of averages of left box */
      numaGetSum(na2, &sum2);  /* sum of averages of right box */
      ave1 = sum1 / h;
      ave2 = 2.0 * sum2 / w;
      ave3 = 0.5 * (ave1 + ave2);  /* average over both halves */
      fprintf(stderr, "ave1 = %8.4f\n", sum1 / h);
      fprintf(stderr, "ave2 = %8.4f\n", 2.0 * sum2 / w);
      pixAverageInRect(pixs, NULL, &ave4);  /* entire image */
      diff1 = ave4 - ave3;
      diff2 = w * h * ave4 - (0.5 * w * sum1 + h * sum2);
      if (diff1 < 0.001)
          fprintf(stderr, "Average diffs are correct\n");
      else
          fprintf(stderr, "Average diffs are wrong: diff1 = %7.5f\n", diff1);
      if (diff2 < 20)  /* float-to-integer roundoff */
          fprintf(stderr, "Pixel sums are correct\n");
      else
          fprintf(stderr, "Pixel sums are in error: diff = %7.0f\n", diff2);
  
          /* Variance left and right halves.  Variance doesn't average
           * in a simple way, unlike pixel sums. */
      pixVarianceInRect(pixs, box1, &var1);  /* entire image */
      pixVarianceInRect(pixs, box2, &var2);  /* entire image */
      pixVarianceInRect(pixs, NULL, &var3);  /* entire image */
      fprintf(stderr, "0.5 * (var1 + var2) = %7.3f, var3 = %7.3f\n",
              0.5 * (var1 + var2), var3);
      boxDestroy(&box1);
      boxDestroy(&box2);
      numaDestroy(&na1);
      numaDestroy(&na2);
  #endif
  
      /* -------------------------------------------------------------------*
       *                     Row and column variances                       *
       * -------------------------------------------------------------------*/
  #if  DO_ALL
  
          /* Display variance by rows and columns */
      box1 = boxCreate(415, 0, 130, 425);
      boxGetGeometry(box1, NULL, NULL, &bw, &bh);
      na1 = pixVarianceByRow(pixs, box1);
      na2 = pixVarianceByColumn(pixs, box1);
      pix = pixConvertTo32(pixs);
      pix1 = pixCopy(NULL, pix);
      pixRenderPlotFromNumaGen(&pix, na1, L_VERTICAL_LINE, 3, 415, 100, 1,
                               0xff000000);
      pixRenderPlotFromNumaGen(&pix, na2, L_HORIZONTAL_LINE, 3, bh / 2, 100, 1,
                            0x00ff0000);
      pixRenderPlotFromNuma(&pix1, na1, L_PLOT_AT_LEFT, 3, 60, 0x00ff0000);
      pixRenderPlotFromNuma(&pix1, na1, L_PLOT_AT_MID_VERT, 3, 60, 0x0000ff00);
      pixRenderPlotFromNuma(&pix1, na1, L_PLOT_AT_RIGHT, 3, 60, 0xff000000);
      pixRenderPlotFromNuma(&pix1, na2, L_PLOT_AT_TOP, 3, 60, 0x0000ff00);
      pixRenderPlotFromNuma(&pix1, na2, L_PLOT_AT_MID_HORIZ, 3, 60, 0xff000000);
      pixRenderPlotFromNuma(&pix1, na2, L_PLOT_AT_BOT, 3, 60, 0x00ff0000);
      pixDisplay(pix, 500, 900);
      pixDisplay(pix1, 500, 1000);
      boxDestroy(&box1);
      numaDestroy(&na1);
      numaDestroy(&na2);
      pixDestroy(&pix);
      pixDestroy(&pix1);
      pixDestroy(&pixs);
  
          /* Again on a different image */
      pix1 = pixRead("boxedpage.jpg");
      pix2 = pixConvertTo8(pix1, 0);
      pixGetDimensions(pix2, &w, &h, NULL);
      na1 = pixVarianceByRow(pix2, NULL);
      pix3 = pixConvertTo32(pix1);
      pixRenderPlotFromNumaGen(&pix3, na1, L_VERTICAL_LINE, 3, 0, 70, 1,
                               0xff000000);
      na2 = pixVarianceByColumn(pix2, NULL);
      pixRenderPlotFromNumaGen(&pix3, na2, L_HORIZONTAL_LINE, 3, bh - 1, 70, 1,
                               0x00ff0000);
      pixDisplay(pix3, 1000, 0);
      numaDestroy(&na1);
      numaDestroy(&na2);
      pixDestroy(&pix3);
  
          /* Again, with an erosion */
      pix3 = pixErodeGray(pix2, 3, 21);
      pixDisplay(pix3, 1400, 0);
      na1 = pixVarianceByRow(pix3, NULL);
      pix4 = pixConvertTo32(pix1);
      pixRenderPlotFromNumaGen(&pix4, na1, L_VERTICAL_LINE, 3, 30, 70, 1,
                               0xff000000);
      na2 = pixVarianceByColumn(pix3, NULL);
      pixRenderPlotFromNumaGen(&pix4, na2, L_HORIZONTAL_LINE, 3, bh - 1, 70, 1,
                               0x00ff0000);
      pixDisplay(pix4, 1000, 550);
      numaDestroy(&na1);
      numaDestroy(&na2);
      pixDestroy(&pix1);
      pixDestroy(&pix2);
      pixDestroy(&pix3);
      pixDestroy(&pix4);
  #endif
  
      /* -------------------------------------------------------------------*
       *                    Windowed variance along a line                  *
       * -------------------------------------------------------------------*/
  #if  DO_ALL
      pix1 = pixRead("boxedpage.jpg");
      pix2 = pixConvertTo8(pix1, 0);
      pixGetDimensions(pix2, &w, &h, NULL);
      pix3 = pixCopy(NULL, pix1);
  
          /* Plot along horizontal line */
      pixWindowedVarianceOnLine(pix2, L_HORIZONTAL_LINE, h / 2 - 30, 0,
                                w, 5, &na1);
      pixRenderPlotFromNumaGen(&pix1, na1, L_HORIZONTAL_LINE, 3, h / 2 - 30,
                               80, 1, 0xff000000);
      pixRenderPlotFromNuma(&pix3, na1, L_PLOT_AT_TOP, 3, 60, 0x00ff0000);
      pixRenderPlotFromNuma(&pix3, na1, L_PLOT_AT_BOT, 3, 60, 0x0000ff00);
  
          /* Plot along vertical line */
      pixWindowedVarianceOnLine(pix2, L_VERTICAL_LINE, 0.78 * w, 0,
                                h, 5, &na2);
      pixRenderPlotFromNumaGen(&pix1, na2, L_VERTICAL_LINE, 3, 0.78 * w, 60,
                               1, 0x00ff0000);
      pixRenderPlotFromNuma(&pix3, na2, L_PLOT_AT_LEFT, 3, 60, 0xff000000);
      pixRenderPlotFromNuma(&pix3, na2, L_PLOT_AT_RIGHT, 3, 60, 0x00ff0000);
      pixDisplay(pix1, 1000, 1000);
      pixDisplay(pix3, 1500, 1000);
      pixDestroy(&pix1);
      pixDestroy(&pix2);
      pixDestroy(&pix3);
      numaDestroy(&na1);
      numaDestroy(&na2);
  #endif
      return 0;
  }
  