Advertisement
Guest User

Untitled

a guest
Dec 12th, 2018
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 236.22 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using Emgu.CV.Structure;
  5. using Emgu.CV;
  6. using System.Diagnostics;
  7. using System.Linq;
  8.  
  9. namespace SS_OpenCV
  10. {
  11.     class ImageClass
  12.     {
  13.         static public void ConvertToGray(Image<Bgr, byte> img)
  14.         {
  15.             unsafe
  16.             {
  17.                 MIplImage m = img.MIplImage;
  18.                 byte* dataPtr = (byte*)m.imageData.ToPointer(); // Pointer to the image
  19.  
  20.                 int width = img.Width;
  21.                 int height = img.Height;
  22.                 int nChan = m.nChannels; // number of channels - 3
  23.                 int widthStep = m.widthStep;
  24.                 int padding = widthStep - nChan * width;
  25.                 int x, y;
  26.                 byte gray;
  27.  
  28.                 if (nChan == 3) // image in RGB
  29.                 {
  30.                     for (y = 0; y < height; y++)
  31.                     {
  32.                         for (x = 0; x < width; x++)
  33.                         {
  34.                             gray = (byte)Math.Round((dataPtr[0] + dataPtr[1] + dataPtr[2]) / 3.0);
  35.  
  36.                             dataPtr[0] = gray;
  37.                             dataPtr[1] = gray;
  38.                             dataPtr[2] = gray;
  39.  
  40.                             dataPtr += nChan;
  41.                         }
  42.                         dataPtr += padding;
  43.                     }
  44.                 } // End of nChan = 3
  45.             } // End of Unsafe
  46.         } // End of Convert to Gray
  47.  
  48.  
  49.         // ***  Required SS Operations  ***
  50.         public static void Negative(Image<Bgr, byte> img)
  51.         {
  52.             unsafe
  53.             {
  54.                 MIplImage m = img.MIplImage;
  55.                 byte* dataPtr = (byte*)m.imageData.ToPointer(); // Pointer to the image
  56.  
  57.                 int width = img.Width;
  58.                 int height = img.Height;
  59.                 int widthStep = m.widthStep;
  60.                 int nChan = m.nChannels; // number of channels - 3
  61.                 int padding = widthStep - nChan * width;
  62.                 int x, y;
  63.  
  64.                 if (nChan == 3) // image in RGB
  65.                 {
  66.                     for (y = 0; y < height; y++)
  67.                     {
  68.                         for (x = 0; x < width; x++)
  69.                         {
  70.                             dataPtr[0] = (byte)(255 - dataPtr[0]);
  71.                             dataPtr[1] = (byte)(255 - dataPtr[1]);
  72.                             dataPtr[2] = (byte)(255 - dataPtr[2]);
  73.  
  74.                             dataPtr += nChan;
  75.                         }
  76.                         dataPtr += padding;
  77.                     }
  78.                 } // End of nChan = 3
  79.             } // End of Unsafe
  80.         } // End of Negative
  81.  
  82.         public static void BrightContrast(Image<Bgr, byte> img, int bright, double contrast)
  83.         {
  84.             unsafe
  85.             {
  86.                 MIplImage m = img.MIplImage;
  87.                 byte* dataPtr = (byte*)m.imageData.ToPointer(); // Pointer to the image
  88.  
  89.                 int width = img.Width;
  90.                 int height = img.Height;
  91.                 int nChan = m.nChannels; // number of channels - 3
  92.                 int widthStep = m.widthStep;
  93.                 int padding = widthStep - nChan * width;
  94.                 int x, y;
  95.                 int b, r, g;
  96.  
  97.                 if (nChan == 3) // image in RGB
  98.                 {
  99.                     for (y = 0; y < height; y++)
  100.                     {
  101.                         for (x = 0; x < width; x++)
  102.                         {
  103.                             b = (int)Math.Round(dataPtr[0] * contrast + bright);
  104.                             if (b > 255)
  105.                                 dataPtr[0] = (byte)255;
  106.                             else if (b < 0)
  107.                                 dataPtr[0] = (byte)0;
  108.                             else
  109.                                 dataPtr[0] = (byte)b;
  110.  
  111.                             g = (int)Math.Round(dataPtr[1] * contrast + bright);
  112.                             if (g > 255)
  113.                                 dataPtr[1] = (byte)255;
  114.                             else if (g < 0)
  115.                                 dataPtr[1] = (byte)0;
  116.                             else
  117.                                 dataPtr[1] = (byte)g;
  118.  
  119.                             r = (int)Math.Round(dataPtr[2] * contrast + bright);
  120.                             if (r > 255)
  121.                                 dataPtr[2] = (byte)255;
  122.                             else if (r < 0)
  123.                                 dataPtr[2] = (byte)0;
  124.                             else
  125.                                 dataPtr[2] = (byte)r;
  126.  
  127.                             dataPtr += nChan;
  128.                         }
  129.                         dataPtr += padding;
  130.                     }
  131.                 } // End of nChan = 3
  132.             } // End of Unsafe
  133.         } // End of Bright Contrast
  134.  
  135.         public static void RedChannel(Image<Bgr, byte> img)
  136.         {
  137.             unsafe
  138.             {
  139.                 MIplImage m = img.MIplImage;
  140.                 byte* dataPtr = (byte*)m.imageData.ToPointer(); // Pointer to the image
  141.  
  142.                 int width = img.Width;
  143.                 int height = img.Height;
  144.                 int nChan = m.nChannels; // number of channels - 3
  145.                 int widthStep = m.widthStep;
  146.                 int padding = widthStep - nChan * width;
  147.                 int x, y;
  148.  
  149.                 if (nChan == 3) // image in RGB
  150.                 {
  151.                     for (y = 0; y < height; y++)
  152.                     {
  153.                         for (x = 0; x < width; x++)
  154.                         {
  155.                             dataPtr[0] = (byte)dataPtr[2];
  156.                             dataPtr[1] = (byte)dataPtr[2];
  157.  
  158.                             dataPtr += nChan;
  159.                         }
  160.                         dataPtr += padding;
  161.                     }
  162.                 } // End of nChan = 3
  163.             } // End of Unsafe
  164.         } // End of Red Channel
  165.  
  166.         public static void Translation(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy, int dx, int dy)
  167.         {
  168.             unsafe
  169.             {
  170.                 MIplImage m = imgCopy.MIplImage;
  171.                 MIplImage d = img.MIplImage;
  172.                 byte* dataPtr_org = (byte*)m.imageData.ToPointer(); // Pointer to the original image
  173.                 byte* dataPtr = (byte*)d.imageData.ToPointer();   // Pointer to the final image
  174.                 byte* px, o_px;
  175.  
  176.                 int width = imgCopy.Width;
  177.                 int height = imgCopy.Height;
  178.                 int widthStep = m.widthStep;
  179.                 int nChan = m.nChannels; // number of channels - 3
  180.                 int padding = widthStep - nChan * width;
  181.  
  182.                 int x, y;
  183.                 int x_blk_inf = 0, x_blk_sup = 0, y_blk_inf = 0, y_blk_sup = 0;
  184.                 int x_img_inf = 0, x_img_sup = 0, y_img_inf = 0, y_img_sup = 0;
  185.  
  186.                 if (dx > 0)
  187.                 {
  188.                     x_blk_inf = 0;
  189.                     x_blk_sup = dx;
  190.                     x_img_inf = dx;
  191.                     x_img_sup = width;
  192.                 }
  193.                 else if (dx < 0)
  194.                 {
  195.                     x_img_inf = 0;
  196.                     x_img_sup = width + dx;
  197.                     x_blk_inf = width + dx;
  198.                     x_blk_sup = width;
  199.                 }
  200.  
  201.                 if (dy > 0)
  202.                 {
  203.                     y_blk_inf = 0;
  204.                     y_blk_sup = dy;
  205.                     y_img_inf = dy;
  206.                     y_img_sup = height;
  207.                 }
  208.                 else if (dy < 0)
  209.                 {
  210.                     y_img_inf = 0;
  211.                     y_img_sup = height + dy;
  212.                     y_blk_inf = height + dy;
  213.                     y_blk_sup = height;
  214.                 }
  215.  
  216.                 if (nChan == 3) // image in RGB
  217.                 {
  218.                     // Process dx bigger rectangle
  219.                     for (y = 0; y < height; y++)
  220.                     {
  221.                         for (x = x_blk_inf; x < x_blk_sup; x++)
  222.                         {
  223.                             px = (dataPtr + y * widthStep + x * nChan);
  224.  
  225.                             px[0] = 0;
  226.                             px[1] = 0;
  227.                             px[2] = 0;
  228.                         }
  229.                     }
  230.  
  231.                     // Process dy smaller rectangle
  232.                     for (y = y_blk_inf; y < y_blk_sup; y++)
  233.                     {
  234.                         for (x = x_img_inf; x < x_img_sup; x++)
  235.                         {
  236.                             px = (dataPtr + y * widthStep + x * nChan);
  237.  
  238.                             px[0] = 0;
  239.                             px[1] = 0;
  240.                             px[2] = 0;
  241.                         }
  242.                     }
  243.  
  244.                     // Process image rectangle
  245.                     for (y = y_img_inf; y < y_img_sup; y++)
  246.                     {
  247.                         for (x = y_img_inf; x < x_img_sup; x++)
  248.                         {
  249.                             px = (dataPtr + y * widthStep + x * nChan);
  250.                             o_px = (dataPtr_org + (y - dy) * widthStep + (x - dx) * nChan);
  251.  
  252.                             // Change Pixels
  253.                             px[0] = (byte)o_px[0];
  254.                             px[1] = (byte)o_px[1];
  255.                             px[2] = (byte)o_px[2];
  256.                         }
  257.                     }
  258.                 } // End of nChan = 3
  259.             } // End of Unsafe
  260.         } // End of Translation - Segmented
  261.  
  262.         public static void Rotation(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy, float angle)
  263.         {
  264.             unsafe
  265.             {
  266.                 MIplImage m = img.MIplImage;
  267.                 MIplImage m1 = imgCopy.MIplImage;
  268.                 byte* dataPtr = (byte*)m.imageData.ToPointer(); // Pointer to the image
  269.                 byte* dataPtrCopy = (byte*)m1.imageData.ToPointer(); // Pointer to the image
  270.                 byte* pxCopy;
  271.  
  272.                 int width = img.Width;
  273.                 int height = img.Height;
  274.                 int nChan = m.nChannels; // number of channels - 3
  275.                 int padding = m.widthStep - m.nChannels * m.width; // alinhament bytes (padding)
  276.                 int x, y;
  277.  
  278.                 double sin = Math.Sin(angle);
  279.                 double cos = Math.Cos(angle);
  280.                 double xc = (-((double)width / 2) * cos) - (((double)height / 2) * sin) + ((double)width / 2);
  281.                 double yc = (((double)width / 2) * sin) - (((double)height / 2) * cos) + ((double)height / 2);
  282.                 int xo, yo;
  283.  
  284.                 if (nChan == 3)
  285.                 {
  286.                     for (y = 0; y < height; y++)
  287.                     {
  288.                         for (x = 0; x < width; x++)
  289.                         {
  290.                             xo = (int)Math.Round(xc + x * cos + y * sin);
  291.                             yo = (int)Math.Round(yc - x * sin + y * cos);
  292.  
  293.                             // calcula endereço do pixel no ponto (x,y)
  294.                             if ((xo >= 0 && xo < width) && (yo >= 0 && yo < height))
  295.                             {
  296.                                 pxCopy = (dataPtrCopy + yo * m.widthStep + xo * nChan);
  297.  
  298.                                 dataPtr[0] = (byte)pxCopy[0];
  299.                                 dataPtr[1] = (byte)pxCopy[1];
  300.                                 dataPtr[2] = (byte)pxCopy[2];
  301.                             }
  302.                             else
  303.                             {
  304.                                 dataPtr[0] = 0;
  305.                                 dataPtr[1] = 0;
  306.                                 dataPtr[2] = 0;
  307.                             }
  308.                             dataPtr += nChan;
  309.                         }
  310.                         dataPtr += padding;
  311.                     }
  312.                 } // End of nChan = 3
  313.             } // End of Unsafe
  314.         } // End of Rotation
  315.  
  316.         public static void Rotation_Bilinear(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy, float angle)
  317.         {
  318.             unsafe
  319.             {
  320.                 MIplImage m = img.MIplImage;
  321.                 MIplImage m1 = imgCopy.MIplImage;
  322.                 byte* dataPtr = (byte*)m.imageData.ToPointer(); // Pointer to the image
  323.                 byte* dataPtrCopy = (byte*)m1.imageData.ToPointer(); // Pointer to the image
  324.  
  325.                 byte* px, pxCopy;
  326.                 byte* a, b, c, d;
  327.  
  328.                 int width = img.Width;
  329.                 int height = img.Height;
  330.                 int widthStep = m.widthStep;
  331.                 int nChan = m.nChannels; // number of channels - 3
  332.                 int padding = m.widthStep - m.nChannels * m.width; // alinhament bytes (padding)
  333.                 int x, y;
  334.  
  335.                 double sin = Math.Sin(angle);
  336.                 double cos = Math.Cos(angle);
  337.                 double xc = (-((double)width / 2) * cos) - (((double)height / 2) * sin) + ((double)width / 2);
  338.                 double yc = (((double)width / 2) * sin) - (((double)height / 2) * cos) + ((double)height / 2);
  339.  
  340.                 double xo, yo;
  341.                 double j, k;
  342.                 double blueS, greenS, redS;
  343.                 double blueI, greenI, redI;
  344.                 int xr, yr; // reduzido ?
  345.  
  346.                 if (nChan == 3)
  347.                 {
  348.                     for (y = 0; y < height; y++)
  349.                     {
  350.                         for (x = 0; x < width; x++)
  351.                         {
  352.                             xo = xc + x * cos + y * sin;
  353.                             yo = yc - x * sin + y * cos;
  354.  
  355.                             j = xo % 1; // parte decimal da coordenada em x
  356.                             k = yo % 1; // parte decimal da coordenada em y
  357.  
  358.                             xr = (int)(xo - j);
  359.                             yr = (int)(yo - k);
  360.  
  361.                             // calcula endereço do pixel no ponto (x,y)
  362.                             if ((xo >= 0 && xo < width) && (yo >= 0 && yo < height))
  363.                             {
  364.                                 if (xo >= width - 1)
  365.                                     xr = width - 2;  // para não passar da imagem quando (xr + 1)
  366.                                 if (yo >= height - 1)
  367.                                     yr = height - 2; // para não passar da imagem quando (yr + 1)
  368.  
  369.                                 pxCopy = (dataPtrCopy + yr * widthStep + xr * nChan);
  370.  
  371.                                 a = (pxCopy);
  372.                                 b = (pxCopy + nChan);
  373.                                 c = (pxCopy + widthStep);
  374.                                 d = (pxCopy + nChan + widthStep);
  375.  
  376.                                 // Bx+j,y = (1 - j) * Bx,y + j * Bx+1,y
  377.                                 blueS = (1 - j) * a[0] + j * b[0];
  378.                                 greenS = (1 - j) * a[1] + j * b[1];
  379.                                 redS = (1 - j) * a[2] + j * b[2];
  380.                                 // Bx+j,y+1 = (1 - j) * Bx,y+1 + j * Bx+1,y+1
  381.                                 blueI = (1 - j) * c[0] + j * d[0];
  382.                                 greenI = (1 - j) * c[1] + j * d[1];
  383.                                 redI = (1 - j) * c[2] + j * d[2];
  384.  
  385.                                 // Bx+j,y+k = (1 - k) * Bx+j,y + k * Bx+j,y+1
  386.                                 dataPtr[0] = (byte)(Math.Round((1 - k) * blueS + k * blueI));
  387.                                 dataPtr[1] = (byte)(Math.Round((1 - k) * greenS + k * greenI));
  388.                                 dataPtr[2] = (byte)(Math.Round((1 - k) * redS + k * redI));
  389.                             }
  390.                             else
  391.                             {
  392.                                 dataPtr[0] = 0;
  393.                                 dataPtr[1] = 0;
  394.                                 dataPtr[2] = 0;
  395.                             }
  396.                             dataPtr += nChan;
  397.                         }
  398.  
  399.                         dataPtr += padding;
  400.                     }
  401.                 } // End of nChan = 3
  402.             } // End of Unsafe
  403.         } // End of Rotation Bilinear
  404.  
  405.         public static void Scale(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy, float scaleFactor)
  406.         {
  407.             unsafe
  408.             {
  409.                 MIplImage m = imgCopy.MIplImage;
  410.                 MIplImage d = img.MIplImage;
  411.                 byte* dataPtr_org = (byte*)m.imageData.ToPointer(); // Pointer to the original image
  412.                 byte* dataPtr = (byte*)d.imageData.ToPointer();   // Pointer to the final image
  413.                 byte* o_px;
  414.  
  415.                 int w = img.Width, h = img.Height;
  416.                 int nChan = m.nChannels; // number of channels - 3
  417.                 int widthStep = m.widthStep;
  418.                 int padding = widthStep - nChan * w;
  419.                 int x, y, x_org, y_org;
  420.  
  421.                 if (nChan == 3) // image in RGB
  422.                 {
  423.                     for (y = 0; y < h; y++)
  424.                     {
  425.                         for (x = 0; x < w; x++)
  426.                         {
  427.                             x_org = (int)Math.Round(x / scaleFactor);
  428.                             y_org = (int)Math.Round(y / scaleFactor);
  429.                             o_px = dataPtr_org + y_org * widthStep + x_org * nChan;
  430.  
  431.                             // Outside of borders
  432.                             if (x_org < 0 || x_org >= w || y_org < 0 || y_org >= h)
  433.                             {
  434.                                 dataPtr[0] = 0;
  435.                                 dataPtr[1] = 0;
  436.                                 dataPtr[2] = 0;
  437.                                 dataPtr += nChan;
  438.                                 continue;
  439.                             }
  440.  
  441.                             // Change Pixels
  442.                             dataPtr[0] = o_px[0];
  443.                             dataPtr[1] = o_px[1];
  444.                             dataPtr[2] = o_px[2];
  445.  
  446.                             dataPtr += nChan;
  447.                         }
  448.                         dataPtr += padding;
  449.                     }
  450.                 } // End of nChan = 3
  451.             } // End of Unsafe
  452.         } // End of Scale
  453.  
  454.         public static void Scale_Bilinear(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy, float scaleFactor)
  455.         {
  456.             unsafe
  457.             {
  458.                 MIplImage m = img.MIplImage;
  459.                 MIplImage m1 = imgCopy.MIplImage;
  460.                 byte* dataPtr = (byte*)m.imageData.ToPointer(); // Pointer to the image
  461.                 byte* dataPtrCopy = (byte*)m1.imageData.ToPointer(); // Pointer to the image
  462.  
  463.                 byte* px, pxCopy;
  464.                 byte* a, b, c, d;
  465.  
  466.                 int width = img.Width;
  467.                 int height = img.Height;
  468.                 int nChan = m.nChannels; // number of channels - 3
  469.                 int widthStep = m.widthStep;
  470.                 int padding = m.widthStep - m.nChannels * m.width; // alinhament bytes (padding)
  471.                 int x, y;
  472.                 double xo, yo;
  473.                 double j, k;
  474.                 double blueS, greenS, redS;
  475.                 double blueI, greenI, redI;
  476.                 int xr, yr; // reduzido ?
  477.  
  478.                 if (nChan == 3)
  479.                 {
  480.                     for (y = 0; y < height; y++)
  481.                     {
  482.                         for (x = 0; x < width; x++)
  483.                         {
  484.                             xo = x / scaleFactor;
  485.                             yo = y / scaleFactor;
  486.  
  487.                             j = xo % 1; // parte decimal da coordenada em x
  488.                             k = yo % 1; // parte decimal da coordenada em y
  489.  
  490.                             xr = (int)(xo - j);
  491.                             yr = (int)(yo - k);
  492.  
  493.                             // calcula endereço do pixel no ponto (x,y)
  494.                             if ((xo >= 0 && xo < width) && (yo >= 0 && yo < height))
  495.                             {
  496.                                 if (xo == width - 1)
  497.                                     xr--;  // para não passar da imagem quando (xr + 1)
  498.                                 if (yo == height - 1)
  499.                                     yr--; // para não passar da imagem quando (yr + 1)
  500.  
  501.                                 pxCopy = (dataPtrCopy + yr * widthStep + xr * nChan);
  502.  
  503.                                 a = (pxCopy);
  504.                                 b = (pxCopy + nChan);
  505.                                 c = (pxCopy + widthStep);
  506.                                 d = (pxCopy + nChan + widthStep);
  507.  
  508.                                 // Bx+j,y = (1 - j) * Bx,y + j * Bx+1,y
  509.                                 blueS = (1 - j) * a[0] + j * b[0];
  510.                                 greenS = (1 - j) * a[1] + j * b[1];
  511.                                 redS = (1 - j) * a[2] + j * b[2];
  512.                                 // Bx+j,y+1 = (1 - j) * Bx,y+1 + j * Bx+1,y+1
  513.                                 blueI = (1 - j) * c[0] + j * d[0];
  514.                                 greenI = (1 - j) * c[1] + j * d[1];
  515.                                 redI = (1 - j) * c[2] + j * d[2];
  516.  
  517.                                 // Bx+j,y+k = (1 - k) * Bx+j,y + k * Bx+j,y+1
  518.                                 dataPtr[0] = (byte)(Math.Round((1 - k) * blueS + k * blueI));
  519.                                 dataPtr[1] = (byte)(Math.Round((1 - k) * greenS + k * greenI));
  520.                                 dataPtr[2] = (byte)(Math.Round((1 - k) * redS + k * redI));
  521.                             }
  522.                             else
  523.                             {
  524.                                 dataPtr[0] = 0;
  525.                                 dataPtr[1] = 0;
  526.                                 dataPtr[2] = 0;
  527.                             }
  528.                             dataPtr += nChan;
  529.                         }
  530.  
  531.                         dataPtr += padding;
  532.                     }
  533.                 } // End of nChan = 3
  534.             } // End of Unsafe
  535.         } // End of Scale Bilinear
  536.  
  537.         public static void Scale_point_xy(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy, float scaleFactor, int centerX, int centerY)
  538.         {
  539.             unsafe
  540.             {
  541.                 MIplImage m = imgCopy.MIplImage;
  542.                 MIplImage f = img.MIplImage;
  543.                 byte* dataPtr_org = (byte*)m.imageData.ToPointer(); // Pointer to the original image
  544.                 byte* dataPtr = (byte*)f.imageData.ToPointer();   // Pointer to the final image
  545.                 byte* px_org;
  546.  
  547.                 int w = img.Width, h = img.Height;
  548.                 int nChan = m.nChannels; // number of channels - 3
  549.                 int widthStep = m.widthStep;
  550.                 int padding = widthStep - nChan * w;
  551.                 int x, y, x_aux, y_aux;
  552.                 int w2 = w / 2, h2 = h / 2;
  553.                 float w2s = w2 / scaleFactor, h2s = h2 / scaleFactor;
  554.  
  555.                 if (nChan == 3) // image in RGB
  556.                 {
  557.                     for (y = 0; y < h; y++)
  558.                     {
  559.                         for (x = 0; x < w; x++)
  560.                         {
  561.                             x_aux = (int)Math.Round(centerX + (x / scaleFactor) - w2s);
  562.                             y_aux = (int)Math.Round(centerY + (y / scaleFactor) - h2s);
  563.                             px_org = dataPtr_org + y_aux * widthStep + x_aux * nChan;
  564.  
  565.                             // Outside of borders
  566.                             if (x_aux < 0 || x_aux >= w || y_aux < 0 || y_aux >= h)
  567.                             {
  568.                                 dataPtr[0] = 0;
  569.                                 dataPtr[1] = 0;
  570.                                 dataPtr[2] = 0;
  571.                                 dataPtr += nChan;
  572.                                 continue;
  573.                             }
  574.  
  575.                             dataPtr[0] = px_org[0];
  576.                             dataPtr[1] = px_org[1];
  577.                             dataPtr[2] = px_org[2];
  578.                             dataPtr += nChan;
  579.                         }
  580.                         dataPtr += padding;
  581.                     }
  582.                 } // End of nChan = 3
  583.             } // End of Unsafe
  584.         } // End of Scale Point XY Bilinear
  585.  
  586.         public static void Scale_point_xy_Bilinear(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy, float scaleFactor, int centerX, int centerY)
  587.         {
  588.             unsafe
  589.             {
  590.                 MIplImage m = img.MIplImage;
  591.                 MIplImage m1 = imgCopy.MIplImage;
  592.                 byte* dataPtr = (byte*)m.imageData.ToPointer(); // Pointer to the image
  593.                 byte* dataPtrCopy = (byte*)m1.imageData.ToPointer(); // Pointer to the image
  594.  
  595.                 byte* px, pxCopy;
  596.                 byte* a, b, c, d;
  597.  
  598.                 int width = img.Width;
  599.                 int height = img.Height;
  600.                 int nChan = m.nChannels; // number of channels - 3
  601.                 int widthStep = m.widthStep;
  602.                 int padding = m.widthStep - m.nChannels * m.width; // alinhament bytes (padding)
  603.  
  604.                 int x, y, Xcent, Ycent;
  605.                 double xo, yo;
  606.                 double j, k;
  607.                 double blueS, greenS, redS;
  608.                 double blueI, greenI, redI;
  609.  
  610.                 int xr, yr; // reduzido ?
  611.  
  612.                 Xcent = width / 2;
  613.                 Ycent = height / 2;
  614.  
  615.                 if (scaleFactor < 1)  //se scale < 1, inverter o referencial de zoom. (diminui a imagem, mantendo o píxel da posição do rato inalterado)
  616.                 {
  617.                     centerX = m.width - centerX;
  618.                     centerY = m.height - centerY;
  619.                 }
  620.  
  621.                 if (nChan == 3)
  622.                 {
  623.                     for (y = 0; y < height; y++)
  624.                     {
  625.                         for (x = 0; x < width; x++)
  626.                         {
  627.                             //mudar o referencial para o centro da image, e deslocá-la para (mouseX,mouseY)
  628.                             xo = (x - Xcent) / scaleFactor + centerX;
  629.                             yo = (y - Ycent) / scaleFactor + centerY;
  630.  
  631.                             j = xo % 1; // parte decimal da coordenada em x
  632.                             k = yo % 1; // parte decimal da coordenada em y
  633.  
  634.                             xr = (int)(xo - j);
  635.                             yr = (int)(yo - k);
  636.  
  637.                             //px = (dataPtr + y * widthStep + x * nChan);
  638.  
  639.                             // calcula endereço do pixel no ponto (x,y)
  640.                             if ((xo >= 0 && xo < width) && (yo >= 0 && yo < height))
  641.                             {
  642.                                 // Neste caso não é estritamente necessário porque é muito difícil o rato ficar na posição (0;0), com scaleFactor = 1, mas por motivos de segurança, fica no código
  643.                                 if (xo == width - 1)
  644.                                     xr--;  // para não passar da imagem quando (xr + 1)
  645.                                 if (yo == height - 1)
  646.                                     yr--; // para não passar da imagem quando (yr + 1)
  647.  
  648.                                 pxCopy = (dataPtrCopy + yr * widthStep + xr * nChan);
  649.  
  650.                                 a = (pxCopy);
  651.                                 b = (pxCopy + nChan);
  652.                                 c = (pxCopy + widthStep);
  653.                                 d = (pxCopy + nChan + widthStep);
  654.  
  655.                                 // Bx+j,y = (1 - j) * Bx,y + j * Bx+1,y
  656.                                 blueS = (1 - j) * a[0] + j * b[0];
  657.                                 greenS = (1 - j) * a[1] + j * b[1];
  658.                                 redS = (1 - j) * a[2] + j * b[2];
  659.  
  660.                                 // Bx+j,y+1 = (1 - j) * Bx,y+1 + j * Bx+1,y+1
  661.                                 blueI = (1 - j) * c[0] + j * d[0];
  662.                                 greenI = (1 - j) * c[1] + j * d[1];
  663.                                 redI = (1 - j) * c[2] + j * d[2];
  664.  
  665.                                 // Bx+j,y+k = (1 - k) * Bx+j,y + k * Bx+j,y+1
  666.                                 dataPtr[0] = (byte)(Math.Round((1 - k) * blueS + k * blueI));
  667.                                 dataPtr[1] = (byte)(Math.Round((1 - k) * greenS + k * greenI));
  668.                                 dataPtr[2] = (byte)(Math.Round((1 - k) * redS + k * redI));
  669.                             }
  670.                             else
  671.                             {
  672.                                 dataPtr[0] = 0;
  673.                                 dataPtr[1] = 0;
  674.                                 dataPtr[2] = 0;
  675.                             }
  676.                             dataPtr += nChan;
  677.                         }
  678.  
  679.                         dataPtr += padding;
  680.                     }
  681.                 } // End of nChan = 3
  682.             } // End of Unsafe
  683.         } // End of Scale Point XY Bilinear
  684.  
  685.         public static void Mean(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy)
  686.         {
  687.             unsafe
  688.             {
  689.                 MIplImage m = imgCopy.MIplImage;
  690.                 MIplImage d = img.MIplImage;
  691.                 byte* dataPtr_org = (byte*)m.imageData.ToPointer(); // Pointer to the original image
  692.                 byte* dataPtr = (byte*)d.imageData.ToPointer();   // Pointer to the final image
  693.                 byte* centerPx, o_centerPx;
  694.  
  695.                 int w = img.Width;
  696.                 int h = img.Height;
  697.                 int nChan = m.nChannels; // number of channels - 3
  698.                 int widthStep = m.widthStep;
  699.                 int padding = widthStep - nChan * w;
  700.                 int x, y;
  701.                 double[] sum = new double[3];
  702.  
  703.                 if (nChan == 3) // image in RGB
  704.                 {
  705.                     // *** Corners ***
  706.                     {
  707.                         // Top Left                    x = 0; y = 0;
  708.                         o_centerPx = dataPtr_org;
  709.                         centerPx = dataPtr;
  710.  
  711.                         sum[0] = (o_centerPx)[0] * 4
  712.                                 + (o_centerPx + nChan)[0] * 2
  713.                                 + (o_centerPx + widthStep)[0] * 2
  714.                                 + (o_centerPx + widthStep + nChan)[0];
  715.                         sum[1] = (o_centerPx)[1] * 4
  716.                                 + (o_centerPx + nChan)[1] * 2
  717.                                 + (o_centerPx + widthStep)[1] * 2
  718.                                 + (o_centerPx + widthStep + nChan)[1];
  719.                         sum[2] = (o_centerPx)[2] * 4
  720.                                 + (o_centerPx + nChan)[2] * 2
  721.                                 + (o_centerPx + widthStep)[2] * 2
  722.                                 + (o_centerPx + widthStep + nChan)[2];
  723.  
  724.                         centerPx[0] = (byte)Math.Round(sum[0] / 9.0);
  725.                         centerPx[1] = (byte)Math.Round(sum[1] / 9.0);
  726.                         centerPx[2] = (byte)Math.Round(sum[2] / 9.0);
  727.  
  728.                         // Top Right                    x = w - 1; y = 0;
  729.                         o_centerPx = dataPtr_org + (w - 1) * nChan;
  730.                         centerPx = dataPtr + (w - 1) * nChan;
  731.  
  732.                         sum[0] = (o_centerPx)[0] * 4
  733.                                 + (o_centerPx - nChan)[0] * 2
  734.                                 + (o_centerPx + widthStep)[0] * 2
  735.                                 + (o_centerPx + widthStep - nChan)[0];
  736.                         sum[1] = (o_centerPx)[1] * 4
  737.                                 + (o_centerPx - nChan)[1] * 2
  738.                                 + (o_centerPx + widthStep)[1] * 2
  739.                                 + (o_centerPx + widthStep - nChan)[1];
  740.                         sum[2] = (o_centerPx)[2] * 4
  741.                                 + (o_centerPx - nChan)[2] * 2
  742.                                 + (o_centerPx + widthStep)[2] * 2
  743.                                 + (o_centerPx + widthStep - nChan)[2];
  744.  
  745.                         centerPx[0] = (byte)Math.Round(sum[0] / 9.0);
  746.                         centerPx[1] = (byte)Math.Round(sum[1] / 9.0);
  747.                         centerPx[2] = (byte)Math.Round(sum[2] / 9.0);
  748.  
  749.                         // Bottom Left                    x = 0; y = h - 1;
  750.                         o_centerPx = dataPtr_org + (h - 1) * widthStep;
  751.                         centerPx = dataPtr + (h - 1) * widthStep;
  752.  
  753.                         sum[0] = (o_centerPx)[0] * 4
  754.                                 + (o_centerPx + nChan)[0] * 2
  755.                                 + (o_centerPx - widthStep)[0] * 2
  756.                                 + (o_centerPx - widthStep + nChan)[0];
  757.                         sum[1] = (o_centerPx)[1] * 4
  758.                                 + (o_centerPx + nChan)[1] * 2
  759.                                 + (o_centerPx - widthStep)[1] * 2
  760.                                 + (o_centerPx - widthStep + nChan)[1];
  761.                         sum[2] = (o_centerPx)[2] * 4
  762.                                 + (o_centerPx + nChan)[2] * 2
  763.                                 + (o_centerPx - widthStep)[2] * 2
  764.                                 + (o_centerPx - widthStep + nChan)[2];
  765.  
  766.                         centerPx[0] = (byte)Math.Round(sum[0] / 9.0);
  767.                         centerPx[1] = (byte)Math.Round(sum[1] / 9.0);
  768.                         centerPx[2] = (byte)Math.Round(sum[2] / 9.0);
  769.  
  770.                         // Bottom Right                    x = w - 1; y = h - 1;
  771.                         o_centerPx = dataPtr_org + (h - 1) * widthStep + (w - 1) * nChan;
  772.                         centerPx = dataPtr + (h - 1) * widthStep + (w - 1) * nChan;
  773.  
  774.                         sum[0] = (o_centerPx)[0] * 4
  775.                                 + (o_centerPx - nChan)[0] * 2
  776.                                 + (o_centerPx - widthStep)[0] * 2
  777.                                 + (o_centerPx - widthStep - nChan)[0];
  778.                         sum[1] = (o_centerPx)[1] * 4
  779.                                 + (o_centerPx - nChan)[1] * 2
  780.                                 + (o_centerPx - widthStep)[1] * 2
  781.                                 + (o_centerPx - widthStep - nChan)[1];
  782.                         sum[2] = (o_centerPx)[2] * 4
  783.                                 + (o_centerPx - nChan)[2] * 2
  784.                                 + (o_centerPx - widthStep)[2] * 2
  785.                                 + (o_centerPx - widthStep - nChan)[2];
  786.  
  787.                         centerPx[0] = (byte)Math.Round(sum[0] / 9.0);
  788.                         centerPx[1] = (byte)Math.Round(sum[1] / 9.0);
  789.                         centerPx[2] = (byte)Math.Round(sum[2] / 9.0);
  790.                     }
  791.  
  792.                     // *** BORDERS ***
  793.                     {
  794.                         // Left
  795.                         for (y = 1; y < h - 1; y++)
  796.                         {
  797.                             dataPtr += widthStep;
  798.                             dataPtr_org += widthStep;
  799.  
  800.                             sum[0] = (dataPtr_org - widthStep)[0] * 2
  801.                                     + (dataPtr_org - widthStep + nChan)[0]
  802.                                     + (dataPtr_org)[0] * 2
  803.                                     + (dataPtr_org + nChan)[0]
  804.                                     + (dataPtr_org + widthStep)[0] * 2
  805.                                     + (dataPtr_org + widthStep + nChan)[0];
  806.                             sum[1] = (dataPtr_org - widthStep)[1] * 2
  807.                                     + (dataPtr_org - widthStep + nChan)[1]
  808.                                     + (dataPtr_org)[1] * 2
  809.                                     + (dataPtr_org + nChan)[1]
  810.                                     + (dataPtr_org + widthStep)[1] * 2
  811.                                     + (dataPtr_org + widthStep + nChan)[1];
  812.                             sum[2] = (dataPtr_org - widthStep)[2] * 2
  813.                                     + (dataPtr_org - widthStep + nChan)[2]
  814.                                     + (dataPtr_org)[2] * 2
  815.                                     + (dataPtr_org + nChan)[2]
  816.                                     + (dataPtr_org + widthStep)[2] * 2
  817.                                     + (dataPtr_org + widthStep + nChan)[2];
  818.  
  819.                             dataPtr[0] = (byte)Math.Round(sum[0] / 9.0);
  820.                             dataPtr[1] = (byte)Math.Round(sum[1] / 9.0);
  821.                             dataPtr[2] = (byte)Math.Round(sum[2] / 9.0);
  822.                         }
  823.  
  824.                         dataPtr_org = (byte*)m.imageData.ToPointer(); // Pointer to the original image
  825.                         dataPtr = (byte*)d.imageData.ToPointer();   // Pointer to the final image
  826.  
  827.                         dataPtr += nChan * (w - 1);
  828.                         dataPtr_org += nChan * (w - 1);
  829.  
  830.                         // Right
  831.                         for (y = 1; y < h - 1; y++)
  832.                         {
  833.                             dataPtr += widthStep;
  834.                             dataPtr_org += widthStep;
  835.  
  836.                             sum[0] = (dataPtr_org - widthStep)[0] * 2
  837.                                     + (dataPtr_org - widthStep - nChan)[0]
  838.                                     + (dataPtr_org)[0] * 2
  839.                                     + (dataPtr_org - nChan)[0]
  840.                                     + (dataPtr_org + widthStep)[0] * 2
  841.                                     + (dataPtr_org + widthStep - nChan)[0];
  842.                             sum[1] = (dataPtr_org - widthStep)[1] * 2
  843.                                     + (dataPtr_org - widthStep - nChan)[1]
  844.                                     + (dataPtr_org)[1] * 2
  845.                                     + (dataPtr_org - nChan)[1]
  846.                                     + (dataPtr_org + widthStep)[1] * 2
  847.                                     + (dataPtr_org + widthStep - nChan)[1];
  848.                             sum[2] = (dataPtr_org - widthStep)[2] * 2
  849.                                     + (dataPtr_org - widthStep - nChan)[2]
  850.                                     + (dataPtr_org)[2] * 2
  851.                                     + (dataPtr_org - nChan)[2]
  852.                                     + (dataPtr_org + widthStep)[2] * 2
  853.                                     + (dataPtr_org + widthStep - nChan)[2];
  854.  
  855.                             dataPtr[0] = (byte)Math.Round(sum[0] / 9.0);
  856.                             dataPtr[1] = (byte)Math.Round(sum[1] / 9.0);
  857.                             dataPtr[2] = (byte)Math.Round(sum[2] / 9.0);
  858.                         }
  859.  
  860.                         dataPtr_org = (byte*)m.imageData.ToPointer(); // Pointer to the original image
  861.                         dataPtr = (byte*)d.imageData.ToPointer();   // Pointer to the final image
  862.  
  863.                         // Top
  864.                         for (x = 1; x < w - 1; x++)
  865.                         {
  866.                             dataPtr += nChan;
  867.                             dataPtr_org += nChan;
  868.  
  869.                             sum[0] = (dataPtr_org - nChan)[0] * 2
  870.                                     + (dataPtr_org)[0] * 2
  871.                                     + (dataPtr_org + nChan)[0] * 2
  872.                                     + (dataPtr_org + widthStep - nChan)[0]
  873.                                     + (dataPtr_org + widthStep)[0]
  874.                                     + (dataPtr_org + widthStep + nChan)[0];
  875.                             sum[1] = (dataPtr_org - nChan)[1] * 2
  876.                                     + (dataPtr_org)[1] * 2
  877.                                     + (dataPtr_org + nChan)[1] * 2
  878.                                     + (dataPtr_org + widthStep - nChan)[1]
  879.                                     + (dataPtr_org + widthStep)[1]
  880.                                     + (dataPtr_org + widthStep + nChan)[1];
  881.                             sum[2] = (dataPtr_org - nChan)[2] * 2
  882.                                     + (dataPtr_org)[2] * 2
  883.                                     + (dataPtr_org + nChan)[2] * 2
  884.                                     + (dataPtr_org + widthStep - nChan)[2]
  885.                                     + (dataPtr_org + widthStep)[2]
  886.                                     + (dataPtr_org + widthStep + nChan)[2];
  887.  
  888.                             dataPtr[0] = (byte)Math.Round(sum[0] / 9.0);
  889.                             dataPtr[1] = (byte)Math.Round(sum[1] / 9.0);
  890.                             dataPtr[2] = (byte)Math.Round(sum[2] / 9.0);
  891.                         }
  892.  
  893.                         dataPtr_org = (byte*)m.imageData.ToPointer(); // Pointer to the original image
  894.                         dataPtr = (byte*)d.imageData.ToPointer();   // Pointer to the final image
  895.  
  896.                         dataPtr += (h - 1) * widthStep;
  897.                         dataPtr_org += (h - 1) * widthStep;
  898.  
  899.                         // Bottom
  900.                         for (x = 1; x < w - 1; x++)
  901.                         {
  902.                             dataPtr += nChan;
  903.                             dataPtr_org += nChan;
  904.  
  905.                             sum[0] = (dataPtr_org - widthStep - nChan)[0]
  906.                                     + (dataPtr_org - widthStep)[0]
  907.                                     + (dataPtr_org - widthStep + nChan)[0]
  908.                                     + (dataPtr_org - nChan)[0] * 2
  909.                                     + (dataPtr_org)[0] * 2
  910.                                     + (dataPtr_org + nChan)[0] * 2;
  911.                             sum[1] = (dataPtr_org - widthStep - nChan)[1]
  912.                                     + (dataPtr_org - widthStep)[1]
  913.                                     + (dataPtr_org - widthStep + nChan)[1]
  914.                                     + (dataPtr_org - nChan)[1] * 2
  915.                                     + (dataPtr_org)[1] * 2
  916.                                     + (dataPtr_org + nChan)[1] * 2;
  917.                             sum[2] = (dataPtr_org - widthStep - nChan)[2]
  918.                                     + (dataPtr_org - widthStep)[2]
  919.                                     + (dataPtr_org - widthStep + nChan)[2]
  920.                                     + (dataPtr_org - nChan)[2] * 2
  921.                                     + (dataPtr_org)[2] * 2
  922.                                     + (dataPtr_org + nChan)[2] * 2;
  923.  
  924.                             dataPtr[0] = (byte)Math.Round(sum[0] / 9.0);
  925.                             dataPtr[1] = (byte)Math.Round(sum[1] / 9.0);
  926.                             dataPtr[2] = (byte)Math.Round(sum[2] / 9.0);
  927.                         }
  928.  
  929.                         dataPtr_org = (byte*)m.imageData.ToPointer(); // Pointer to the original image
  930.                         dataPtr = (byte*)d.imageData.ToPointer();   // Pointer to the final image
  931.  
  932.                         dataPtr += widthStep + nChan;
  933.                         dataPtr_org += widthStep + nChan;
  934.                     }
  935.  
  936.                     // *** CORE ***
  937.                     for (y = 1; y < h - 1; y++)
  938.                     {
  939.                         for (x = 1; x < w - 1; x++)
  940.                         {
  941.                             sum[0] = (dataPtr_org - widthStep - nChan)[0]
  942.                                     + (dataPtr_org - widthStep)[0]
  943.                                     + (dataPtr_org - widthStep + nChan)[0]
  944.                                     + (dataPtr_org - nChan)[0]
  945.                                     + (dataPtr_org)[0]
  946.                                     + (dataPtr_org + nChan)[0]
  947.                                     + (dataPtr_org + widthStep - nChan)[0]
  948.                                     + (dataPtr_org + widthStep)[0]
  949.                                     + (dataPtr_org + widthStep + nChan)[0];
  950.  
  951.                             sum[1] = (dataPtr_org - widthStep - nChan)[1]
  952.                                     + (dataPtr_org - widthStep)[1]
  953.                                     + (dataPtr_org - widthStep + nChan)[1]
  954.                                     + (dataPtr_org - nChan)[1]
  955.                                     + (dataPtr_org)[1]
  956.                                     + (dataPtr_org + nChan)[1]
  957.                                     + (dataPtr_org + widthStep - nChan)[1]
  958.                                     + (dataPtr_org + widthStep)[1]
  959.                                     + (dataPtr_org + widthStep + nChan)[1];
  960.  
  961.                             sum[2] = (dataPtr_org - widthStep - nChan)[2]
  962.                                     + (dataPtr_org - widthStep)[2]
  963.                                     + (dataPtr_org - widthStep + nChan)[2]
  964.                                     + (dataPtr_org - nChan)[2]
  965.                                     + (dataPtr_org)[2]
  966.                                     + (dataPtr_org + nChan)[2]
  967.                                     + (dataPtr_org + widthStep - nChan)[2]
  968.                                     + (dataPtr_org + widthStep)[2]
  969.                                     + (dataPtr_org + widthStep + nChan)[2];
  970.  
  971.                             dataPtr[0] = (byte)Math.Round(sum[0] / 9.0);
  972.                             dataPtr[1] = (byte)Math.Round(sum[1] / 9.0);
  973.                             dataPtr[2] = (byte)Math.Round(sum[2] / 9.0);
  974.  
  975.                             dataPtr += nChan;
  976.                             dataPtr_org += nChan;
  977.                         }
  978.                         dataPtr += padding + 2 * nChan;
  979.                         dataPtr_org += padding + 2 * nChan;
  980.                     }
  981.                 } // End of nChan = 3
  982.             } // End of Unsafe
  983.         } // End of Mean
  984.  
  985.         public static void Mean_solutionB(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy)
  986.         {
  987.             unsafe
  988.             {
  989.                 // direct access to the image memory(sequencial)
  990.                 // direcion top left -> bottom right
  991.                 MIplImage m = img.MIplImage;
  992.                 MIplImage m1 = imgCopy.MIplImage;
  993.                 byte* dataPtr = (byte*)m.imageData.ToPointer(); // Pointer to the image
  994.                 byte* dataPtrred = dataPtr;
  995.                 byte* auxdataPtr = (byte*)m1.imageData.ToPointer(); // Pointer to the image
  996.                 byte* dataPtrStatic = auxdataPtr; // Pointer de referência para o início da imagem a editar
  997.  
  998.                 int width = img.Width;
  999.                 int height = img.Height;
  1000.                 int nChan = m.nChannels; // number of channels - 3
  1001.                 int padding = m.widthStep - m.nChannels * m.width; // alinhament bytes (padding)
  1002.                 int x = 0, y = 0;
  1003.                 float Iblue, Igreen, Ired;
  1004.                 float Iblueaux, Igreenaux, Iredaux;
  1005.                 float blueSUM, greenSUM, redSUM;
  1006.  
  1007.                 if (nChan == 3)
  1008.                 {
  1009.                     //y = 0, 0 <= x < width
  1010.  
  1011.                     Iblue = 4 * dataPtrStatic[0];
  1012.                     Igreen = 4 * dataPtrStatic[1];
  1013.                     Ired = 4 * dataPtrStatic[2];
  1014.  
  1015.                     Iblue += 2 * (dataPtrStatic + nChan)[0];
  1016.                     Igreen += 2 * (dataPtrStatic + nChan)[1];
  1017.                     Ired += 2 * (dataPtrStatic + nChan)[2];
  1018.  
  1019.                     Iblue += (dataPtrStatic + m.widthStep + nChan)[0];
  1020.                     Igreen += (dataPtrStatic + m.widthStep + nChan)[1];
  1021.                     Ired += (dataPtrStatic + m.widthStep + nChan)[2];
  1022.  
  1023.                     Iblue += 2 * (dataPtrStatic + m.widthStep)[0];
  1024.                     Igreen += 2 * (dataPtrStatic + m.widthStep)[1];
  1025.                     Ired += 2 * (dataPtrStatic + m.widthStep)[2];
  1026.  
  1027.                     Iblueaux = Iblue;
  1028.                     Igreenaux = Igreen;
  1029.                     Iredaux = Ired;
  1030.  
  1031.                     blueSUM = (float)Math.Round(Iblue / 9);
  1032.                     greenSUM = (float)Math.Round(Igreen / 9);
  1033.                     redSUM = (float)Math.Round(Ired / 9);
  1034.  
  1035.                     if (blueSUM > 255) blueSUM = 255;
  1036.                     else if (blueSUM < 0) blueSUM = 0;
  1037.  
  1038.                     if (greenSUM > 255) greenSUM = 255;
  1039.                     else if (greenSUM < 0) greenSUM = 0;
  1040.  
  1041.                     if (redSUM > 255) redSUM = 255;
  1042.                     else if (redSUM < 0) redSUM = 0;
  1043.  
  1044.                     dataPtr[0] = (byte)blueSUM;
  1045.                     dataPtr[1] = (byte)greenSUM;
  1046.                     dataPtr[2] = (byte)redSUM;
  1047.  
  1048.                     //y = 0, x = 1
  1049.                     x++;
  1050.  
  1051.                     dataPtr = dataPtrred + y * m.widthStep + x * nChan;
  1052.  
  1053.                     Iblue += 2 * (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[0] - 2 * (dataPtrStatic + y * m.widthStep + (x - 1) * nChan)[0];
  1054.                     Igreen += 2 * (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[1] - 2 * (dataPtrStatic + y * m.widthStep + (x - 1) * nChan)[1];
  1055.                     Ired += 2 * (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[2] - 2 * (dataPtrStatic + y * m.widthStep + (x - 1) * nChan)[2];
  1056.  
  1057.                     Iblue += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[0] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 1) * nChan)[0];
  1058.                     Igreen += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[1] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 1) * nChan)[1];
  1059.                     Ired += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[2] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 1) * nChan)[2];
  1060.  
  1061.                     blueSUM = (float)Math.Round(Iblue / 9);
  1062.                     greenSUM = (float)Math.Round(Igreen / 9);
  1063.                     redSUM = (float)Math.Round(Ired / 9);
  1064.  
  1065.                     if (blueSUM > 255) blueSUM = 255;
  1066.                     else if (blueSUM < 0) blueSUM = 0;
  1067.  
  1068.                     if (greenSUM > 255) greenSUM = 255;
  1069.                     else if (greenSUM < 0) greenSUM = 0;
  1070.  
  1071.                     if (redSUM > 255) redSUM = 255;
  1072.                     else if (redSUM < 0) redSUM = 0;
  1073.  
  1074.                     dataPtr[0] = (byte)blueSUM;
  1075.                     dataPtr[1] = (byte)greenSUM;
  1076.                     dataPtr[2] = (byte)redSUM;
  1077.  
  1078.                     //y = 0, x = 2
  1079.                     for (x = 2; x < width - 1; x++)
  1080.                     {
  1081.                         dataPtr = dataPtrred + y * m.widthStep + x * nChan;
  1082.  
  1083.                         Iblue += 2 * (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[0] - 2 * (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[0];
  1084.                         Igreen += 2 * (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[1] - 2 * (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[1];
  1085.                         Ired += 2 * (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[2] - 2 * (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[2];
  1086.  
  1087.                         Iblue += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[0] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 2) * nChan)[0];
  1088.                         Igreen += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[1] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 2) * nChan)[1];
  1089.                         Ired += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[2] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 2) * nChan)[2];
  1090.  
  1091.                         blueSUM = (float)Math.Round(Iblue / 9);
  1092.                         greenSUM = (float)Math.Round(Igreen / 9);
  1093.                         redSUM = (float)Math.Round(Ired / 9);
  1094.  
  1095.                         if (blueSUM > 255) blueSUM = 255;
  1096.                         else if (blueSUM < 0) blueSUM = 0;
  1097.  
  1098.                         if (greenSUM > 255) greenSUM = 255;
  1099.                         else if (greenSUM < 0) greenSUM = 0;
  1100.  
  1101.                         if (redSUM > 255) redSUM = 255;
  1102.                         else if (redSUM < 0) redSUM = 0;
  1103.  
  1104.                         dataPtr[0] = (byte)blueSUM;
  1105.                         dataPtr[1] = (byte)greenSUM;
  1106.                         dataPtr[2] = (byte)redSUM;
  1107.                     }
  1108.  
  1109.                     //x = width - 1
  1110.                     dataPtr = dataPtrred + y * m.widthStep + x * nChan;
  1111.  
  1112.                     Iblue += 2 * (dataPtrStatic + y * m.widthStep + x * nChan)[0] - 2 * (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[0];
  1113.                     Igreen += 2 * (dataPtrStatic + y * m.widthStep + x * nChan)[1] - 2 * (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[1];
  1114.                     Ired += 2 * (dataPtrStatic + y * m.widthStep + x * nChan)[2] - 2 * (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[2];
  1115.  
  1116.                     Iblue += (dataPtrStatic + (y + 1) * m.widthStep + x * nChan)[0] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 2) * nChan)[0];
  1117.                     Igreen += (dataPtrStatic + (y + 1) * m.widthStep + x * nChan)[1] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 2) * nChan)[1];
  1118.                     Ired += (dataPtrStatic + (y + 1) * m.widthStep + x * nChan)[2] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 2) * nChan)[2];
  1119.  
  1120.                     blueSUM = (float)Math.Round(Iblue / 9);
  1121.                     greenSUM = (float)Math.Round(Igreen / 9);
  1122.                     redSUM = (float)Math.Round(Ired / 9);
  1123.  
  1124.                     if (blueSUM > 255) blueSUM = 255;
  1125.                     else if (blueSUM < 0) blueSUM = 0;
  1126.  
  1127.                     if (greenSUM > 255) greenSUM = 255;
  1128.                     else if (greenSUM < 0) greenSUM = 0;
  1129.  
  1130.                     if (redSUM > 255) redSUM = 255;
  1131.                     else if (redSUM < 0) redSUM = 0;
  1132.  
  1133.                     dataPtr[0] = (byte)blueSUM;
  1134.                     dataPtr[1] = (byte)greenSUM;
  1135.                     dataPtr[2] = (byte)redSUM;
  1136.  
  1137.                     x = 0;
  1138.                     y = 1;
  1139.  
  1140.                     // y = 1, x = 0
  1141.                     dataPtr = dataPtrred + y * m.widthStep + x * nChan;
  1142.  
  1143.                     Iblue = Iblueaux;
  1144.                     Igreen = Igreenaux;
  1145.                     Ired = Iredaux;
  1146.  
  1147.                     Iblue += 2 * (dataPtrStatic + (y + 1) * m.widthStep + x * nChan)[0] - 2 * (dataPtrStatic + (y - 1) * m.widthStep + x * nChan)[0];
  1148.                     Igreen += 2 * (dataPtrStatic + (y + 1) * m.widthStep + x * nChan)[1] - 2 * (dataPtrStatic + (y - 1) * m.widthStep + x * nChan)[1];
  1149.                     Ired += 2 * (dataPtrStatic + (y + 1) * m.widthStep + x * nChan)[2] - 2 * (dataPtrStatic + (y - 1) * m.widthStep + x * nChan)[2];
  1150.  
  1151.                     Iblue += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[0] - (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[0];
  1152.                     Igreen += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[1] - (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[1];
  1153.                     Ired += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[2] - (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[2];
  1154.  
  1155.                     Iblueaux = Iblue;
  1156.                     Igreenaux = Igreen;
  1157.                     Iredaux = Ired;
  1158.  
  1159.                     blueSUM = (float)Math.Round(Iblue / 9);
  1160.                     greenSUM = (float)Math.Round(Igreen / 9);
  1161.                     redSUM = (float)Math.Round(Ired / 9);
  1162.  
  1163.                     if (blueSUM > 255) blueSUM = 255;
  1164.                     else if (blueSUM < 0) blueSUM = 0;
  1165.  
  1166.                     if (greenSUM > 255) greenSUM = 255;
  1167.                     else if (greenSUM < 0) greenSUM = 0;
  1168.  
  1169.                     if (redSUM > 255) redSUM = 255;
  1170.                     else if (redSUM < 0) redSUM = 0;
  1171.  
  1172.                     dataPtr[0] = (byte)blueSUM;
  1173.                     dataPtr[1] = (byte)greenSUM;
  1174.                     dataPtr[2] = (byte)redSUM;
  1175.  
  1176.                     // y = 1, x = 1
  1177.                     x = 1;
  1178.  
  1179.                     dataPtr = dataPtrred + y * m.widthStep + x * nChan;
  1180.  
  1181.                     Iblue += (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[0] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 1) * nChan)[0];
  1182.                     Igreen += (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[1] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 1) * nChan)[1];
  1183.                     Ired += (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[2] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 1) * nChan)[2];
  1184.  
  1185.                     Iblue += (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[0] - (dataPtrStatic + y * m.widthStep + (x - 1) * nChan)[0];
  1186.                     Igreen += (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[1] - (dataPtrStatic + y * m.widthStep + (x - 1) * nChan)[1];
  1187.                     Ired += (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[2] - (dataPtrStatic + y * m.widthStep + (x - 1) * nChan)[2];
  1188.  
  1189.                     Iblue += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[0] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 1) * nChan)[0];
  1190.                     Igreen += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[1] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 1) * nChan)[1];
  1191.                     Ired += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[2] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 1) * nChan)[2];
  1192.  
  1193.                     blueSUM = (float)Math.Round(Iblue / 9);
  1194.                     greenSUM = (float)Math.Round(Igreen / 9);
  1195.                     redSUM = (float)Math.Round(Ired / 9);
  1196.  
  1197.                     if (blueSUM > 255) blueSUM = 255;
  1198.                     else if (blueSUM < 0) blueSUM = 0;
  1199.  
  1200.                     if (greenSUM > 255) greenSUM = 255;
  1201.                     else if (greenSUM < 0) greenSUM = 0;
  1202.  
  1203.                     if (redSUM > 255) redSUM = 255;
  1204.                     else if (redSUM < 0) redSUM = 0;
  1205.  
  1206.                     dataPtr[0] = (byte)blueSUM;
  1207.                     dataPtr[1] = (byte)greenSUM;
  1208.                     dataPtr[2] = (byte)redSUM;
  1209.  
  1210.                     for (x = 2; x < width - 1; x++)
  1211.                     {
  1212.                         dataPtr = dataPtrred + y * m.widthStep + x * nChan;
  1213.  
  1214.                         Iblue += (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[0] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 2) * nChan)[0];
  1215.                         Igreen += (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[1] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 2) * nChan)[1];
  1216.                         Ired += (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[2] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 2) * nChan)[2];
  1217.  
  1218.                         Iblue += (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[0] - (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[0];
  1219.                         Igreen += (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[1] - (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[1];
  1220.                         Ired += (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[2] - (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[2];
  1221.  
  1222.                         Iblue += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[0] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 2) * nChan)[0];
  1223.                         Igreen += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[1] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 2) * nChan)[1];
  1224.                         Ired += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[2] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 2) * nChan)[2];
  1225.  
  1226.                         blueSUM = (float)Math.Round(Iblue / 9);
  1227.                         greenSUM = (float)Math.Round(Igreen / 9);
  1228.                         redSUM = (float)Math.Round(Ired / 9);
  1229.  
  1230.                         if (blueSUM > 255) blueSUM = 255;
  1231.                         else if (blueSUM < 0) blueSUM = 0;
  1232.  
  1233.                         if (greenSUM > 255) greenSUM = 255;
  1234.                         else if (greenSUM < 0) greenSUM = 0;
  1235.  
  1236.                         if (redSUM > 255) redSUM = 255;
  1237.                         else if (redSUM < 0) redSUM = 0;
  1238.  
  1239.                         dataPtr[0] = (byte)blueSUM;
  1240.                         dataPtr[1] = (byte)greenSUM;
  1241.                         dataPtr[2] = (byte)redSUM;
  1242.                     }
  1243.  
  1244.                     // x = width - 1
  1245.                     dataPtr = dataPtrred + y * m.widthStep + x * nChan;
  1246.  
  1247.                     Iblue += (dataPtrStatic + (y - 1) * m.widthStep + x * nChan)[0] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 2) * nChan)[0];
  1248.                     Igreen += (dataPtrStatic + (y - 1) * m.widthStep + x * nChan)[1] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 2) * nChan)[1];
  1249.                     Ired += (dataPtrStatic + (y - 1) * m.widthStep + x * nChan)[2] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 2) * nChan)[2];
  1250.  
  1251.                     Iblue += (dataPtrStatic + y * m.widthStep + x * nChan)[0] - (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[0];
  1252.                     Igreen += (dataPtrStatic + y * m.widthStep + x * nChan)[1] - (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[1];
  1253.                     Ired += (dataPtrStatic + y * m.widthStep + x * nChan)[2] - (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[2];
  1254.  
  1255.                     Iblue += (dataPtrStatic + (y + 1) * m.widthStep + x * nChan)[0] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 2) * nChan)[0];
  1256.                     Igreen += (dataPtrStatic + (y + 1) * m.widthStep + x * nChan)[1] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 2) * nChan)[1];
  1257.                     Ired += (dataPtrStatic + (y + 1) * m.widthStep + x * nChan)[2] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 2) * nChan)[2];
  1258.  
  1259.                     blueSUM = (float)Math.Round(Iblue / 9);
  1260.                     greenSUM = (float)Math.Round(Igreen / 9);
  1261.                     redSUM = (float)Math.Round(Ired / 9);
  1262.  
  1263.                     if (blueSUM > 255) blueSUM = 255;
  1264.                     else if (blueSUM < 0) blueSUM = 0;
  1265.  
  1266.                     if (greenSUM > 255) greenSUM = 255;
  1267.                     else if (greenSUM < 0) greenSUM = 0;
  1268.  
  1269.                     if (redSUM > 255) redSUM = 255;
  1270.                     else if (redSUM < 0) redSUM = 0;
  1271.  
  1272.                     dataPtr[0] = (byte)blueSUM;
  1273.                     dataPtr[1] = (byte)greenSUM;
  1274.                     dataPtr[2] = (byte)redSUM;
  1275.  
  1276.                     // 1 < y < height, 0 <= x < width
  1277.                     for (y = 2; y < height - 1; y++)
  1278.                     {
  1279.                         // x = 0
  1280.                         x = 0;
  1281.                         dataPtr = dataPtrred + y * m.widthStep + x * nChan;
  1282.  
  1283.                         Iblue = Iblueaux;
  1284.                         Igreen = Igreenaux;
  1285.                         Ired = Iredaux;
  1286.  
  1287.                         Iblue += 2 * (dataPtrStatic + (y + 1) * m.widthStep + x * nChan)[0] - 2 * (dataPtrStatic + (y - 2) * m.widthStep + x * nChan)[0];
  1288.                         Igreen += 2 * (dataPtrStatic + (y + 1) * m.widthStep + x * nChan)[1] - 2 * (dataPtrStatic + (y - 2) * m.widthStep + x * nChan)[1];
  1289.                         Ired += 2 * (dataPtrStatic + (y + 1) * m.widthStep + x * nChan)[2] - 2 * (dataPtrStatic + (y - 2) * m.widthStep + x * nChan)[2];
  1290.  
  1291.                         Iblue += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[0] - (dataPtrStatic + (y - 2) * m.widthStep + (x + 1) * nChan)[0];
  1292.                         Igreen += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[1] - (dataPtrStatic + (y - 2) * m.widthStep + (x + 1) * nChan)[1];
  1293.                         Ired += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[2] - (dataPtrStatic + (y - 2) * m.widthStep + (x + 1) * nChan)[2];
  1294.  
  1295.                         Iblueaux = Iblue;
  1296.                         Igreenaux = Igreen;
  1297.                         Iredaux = Ired;
  1298.  
  1299.                         blueSUM = (float)Math.Round(Iblue / 9);
  1300.                         greenSUM = (float)Math.Round(Igreen / 9);
  1301.                         redSUM = (float)Math.Round(Ired / 9);
  1302.  
  1303.                         if (blueSUM > 255) blueSUM = 255;
  1304.                         else if (blueSUM < 0) blueSUM = 0;
  1305.  
  1306.                         if (greenSUM > 255) greenSUM = 255;
  1307.                         else if (greenSUM < 0) greenSUM = 0;
  1308.  
  1309.                         if (redSUM > 255) redSUM = 255;
  1310.                         else if (redSUM < 0) redSUM = 0;
  1311.  
  1312.                         dataPtr[0] = (byte)blueSUM;
  1313.                         dataPtr[1] = (byte)greenSUM;
  1314.                         dataPtr[2] = (byte)redSUM;
  1315.  
  1316.                         // x = 1
  1317.                         x = 1;
  1318.                         dataPtr = dataPtrred + y * m.widthStep + x * nChan;
  1319.  
  1320.                         Iblue += (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[0] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 1) * nChan)[0];
  1321.                         Igreen += (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[1] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 1) * nChan)[1];
  1322.                         Ired += (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[2] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 1) * nChan)[2];
  1323.  
  1324.                         Iblue += (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[0] - (dataPtrStatic + y * m.widthStep + (x - 1) * nChan)[0];
  1325.                         Igreen += (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[1] - (dataPtrStatic + y * m.widthStep + (x - 1) * nChan)[1];
  1326.                         Ired += (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[2] - (dataPtrStatic + y * m.widthStep + (x - 1) * nChan)[2];
  1327.  
  1328.                         Iblue += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[0] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 1) * nChan)[0];
  1329.                         Igreen += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[1] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 1) * nChan)[1];
  1330.                         Ired += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[2] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 1) * nChan)[2];
  1331.  
  1332.                         blueSUM = (float)Math.Round(Iblue / 9);
  1333.                         greenSUM = (float)Math.Round(Igreen / 9);
  1334.                         redSUM = (float)Math.Round(Ired / 9);
  1335.  
  1336.                         if (blueSUM > 255) blueSUM = 255;
  1337.                         else if (blueSUM < 0) blueSUM = 0;
  1338.  
  1339.                         if (greenSUM > 255) greenSUM = 255;
  1340.                         else if (greenSUM < 0) greenSUM = 0;
  1341.  
  1342.                         if (redSUM > 255) redSUM = 255;
  1343.                         else if (redSUM < 0) redSUM = 0;
  1344.  
  1345.                         dataPtr[0] = (byte)blueSUM;
  1346.                         dataPtr[1] = (byte)greenSUM;
  1347.                         dataPtr[2] = (byte)redSUM;
  1348.  
  1349.                         // x = 2
  1350.                         for (x = 2; x < width - 1; x++)
  1351.                         {
  1352.                             dataPtr = dataPtrred + y * m.widthStep + x * nChan;
  1353.  
  1354.                             Iblue += (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[0] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 2) * nChan)[0];
  1355.                             Igreen += (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[1] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 2) * nChan)[1];
  1356.                             Ired += (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[2] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 2) * nChan)[2];
  1357.  
  1358.                             Iblue += (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[0] - (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[0];
  1359.                             Igreen += (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[1] - (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[1];
  1360.                             Ired += (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[2] - (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[2];
  1361.  
  1362.                             Iblue += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[0] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 2) * nChan)[0];
  1363.                             Igreen += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[1] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 2) * nChan)[1];
  1364.                             Ired += (dataPtrStatic + (y + 1) * m.widthStep + (x + 1) * nChan)[2] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 2) * nChan)[2];
  1365.  
  1366.                             blueSUM = (float)Math.Round(Iblue / 9);
  1367.                             greenSUM = (float)Math.Round(Igreen / 9);
  1368.                             redSUM = (float)Math.Round(Ired / 9);
  1369.  
  1370.                             if (blueSUM > 255) blueSUM = 255;
  1371.                             else if (blueSUM < 0) blueSUM = 0;
  1372.  
  1373.                             if (greenSUM > 255) greenSUM = 255;
  1374.                             else if (greenSUM < 0) greenSUM = 0;
  1375.  
  1376.                             if (redSUM > 255) redSUM = 255;
  1377.                             else if (redSUM < 0) redSUM = 0;
  1378.  
  1379.                             dataPtr[0] = (byte)blueSUM;
  1380.                             dataPtr[1] = (byte)greenSUM;
  1381.                             dataPtr[2] = (byte)redSUM;
  1382.                         }
  1383.  
  1384.                         // x = width - 1
  1385.                         dataPtr = dataPtrred + y * m.widthStep + x * nChan;
  1386.  
  1387.                         Iblue += (dataPtrStatic + (y - 1) * m.widthStep + x * nChan)[0] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 2) * nChan)[0];
  1388.                         Igreen += (dataPtrStatic + (y - 1) * m.widthStep + x * nChan)[1] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 2) * nChan)[1];
  1389.                         Ired += (dataPtrStatic + (y - 1) * m.widthStep + x * nChan)[2] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 2) * nChan)[2];
  1390.  
  1391.                         Iblue += (dataPtrStatic + y * m.widthStep + x * nChan)[0] - (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[0];
  1392.                         Igreen += (dataPtrStatic + y * m.widthStep + x * nChan)[1] - (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[1];
  1393.                         Ired += (dataPtrStatic + y * m.widthStep + x * nChan)[2] - (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[2];
  1394.  
  1395.                         Iblue += (dataPtrStatic + (y + 1) * m.widthStep + x * nChan)[0] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 2) * nChan)[0];
  1396.                         Igreen += (dataPtrStatic + (y + 1) * m.widthStep + x * nChan)[1] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 2) * nChan)[1];
  1397.                         Ired += (dataPtrStatic + (y + 1) * m.widthStep + x * nChan)[2] - (dataPtrStatic + (y + 1) * m.widthStep + (x - 2) * nChan)[2];
  1398.  
  1399.                         blueSUM = (float)Math.Round(Iblue / 9);
  1400.                         greenSUM = (float)Math.Round(Igreen / 9);
  1401.                         redSUM = (float)Math.Round(Ired / 9);
  1402.  
  1403.                         if (blueSUM > 255) blueSUM = 255;
  1404.                         else if (blueSUM < 0) blueSUM = 0;
  1405.  
  1406.                         if (greenSUM > 255) greenSUM = 255;
  1407.                         else if (greenSUM < 0) greenSUM = 0;
  1408.  
  1409.                         if (redSUM > 255) redSUM = 255;
  1410.                         else if (redSUM < 0) redSUM = 0;
  1411.  
  1412.                         dataPtr[0] = (byte)blueSUM;
  1413.                         dataPtr[1] = (byte)greenSUM;
  1414.                         dataPtr[2] = (byte)redSUM;
  1415.                     }
  1416.  
  1417.                     // y = height - 1, x = 0
  1418.                     x = 0;
  1419.  
  1420.                     dataPtr = dataPtrred + y * m.widthStep + x * nChan;
  1421.  
  1422.                     Iblue = Iblueaux;
  1423.                     Igreen = Igreenaux;
  1424.                     Ired = Iredaux;
  1425.  
  1426.                     Iblue += 2 * (dataPtrStatic + y * m.widthStep + x * nChan)[0] - 2 * (dataPtrStatic + (y - 2) * m.widthStep + x * nChan)[0];
  1427.                     Igreen += 2 * (dataPtrStatic + y * m.widthStep + x * nChan)[1] - 2 * (dataPtrStatic + (y - 2) * m.widthStep + x * nChan)[1];
  1428.                     Ired += 2 * (dataPtrStatic + y * m.widthStep + x * nChan)[2] - 2 * (dataPtrStatic + (y - 2) * m.widthStep + x * nChan)[2];
  1429.  
  1430.                     Iblue += (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[0] - (dataPtrStatic + (y - 2) * m.widthStep + (x + 1) * nChan)[0];
  1431.                     Igreen += (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[1] - (dataPtrStatic + (y - 2) * m.widthStep + (x + 1) * nChan)[1];
  1432.                     Ired += (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[2] - (dataPtrStatic + (y - 2) * m.widthStep + (x + 1) * nChan)[2];
  1433.  
  1434.                     blueSUM = (float)Math.Round(Iblue / 9);
  1435.                     greenSUM = (float)Math.Round(Igreen / 9);
  1436.                     redSUM = (float)Math.Round(Ired / 9);
  1437.  
  1438.                     if (blueSUM > 255) blueSUM = 255;
  1439.                     else if (blueSUM < 0) blueSUM = 0;
  1440.  
  1441.                     if (greenSUM > 255) greenSUM = 255;
  1442.                     else if (greenSUM < 0) greenSUM = 0;
  1443.  
  1444.                     if (redSUM > 255) redSUM = 255;
  1445.                     else if (redSUM < 0) redSUM = 0;
  1446.  
  1447.                     dataPtr[0] = (byte)blueSUM;
  1448.                     dataPtr[1] = (byte)greenSUM;
  1449.                     dataPtr[2] = (byte)redSUM;
  1450.  
  1451.                     x = 1;
  1452.  
  1453.                     dataPtr = dataPtrred + y * m.widthStep + x * nChan;
  1454.  
  1455.                     Iblue += 2 * (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[0] - 2 * (dataPtrStatic + y * m.widthStep + (x - 1) * nChan)[0];
  1456.                     Igreen += 2 * (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[1] - 2 * (dataPtrStatic + y * m.widthStep + (x - 1) * nChan)[1];
  1457.                     Ired += 2 * (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[2] - 2 * (dataPtrStatic + y * m.widthStep + (x - 1) * nChan)[2];
  1458.  
  1459.                     Iblue += (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[0] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 1) * nChan)[0];
  1460.                     Igreen += (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[1] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 1) * nChan)[1];
  1461.                     Ired += (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[2] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 1) * nChan)[2];
  1462.  
  1463.                     blueSUM = (float)Math.Round(Iblue / 9);
  1464.                     greenSUM = (float)Math.Round(Igreen / 9);
  1465.                     redSUM = (float)Math.Round(Ired / 9);
  1466.  
  1467.                     if (blueSUM > 255) blueSUM = 255;
  1468.                     else if (blueSUM < 0) blueSUM = 0;
  1469.  
  1470.                     if (greenSUM > 255) greenSUM = 255;
  1471.                     else if (greenSUM < 0) greenSUM = 0;
  1472.  
  1473.                     if (redSUM > 255) redSUM = 255;
  1474.                     else if (redSUM < 0) redSUM = 0;
  1475.  
  1476.                     dataPtr[0] = (byte)blueSUM;
  1477.                     dataPtr[1] = (byte)greenSUM;
  1478.                     dataPtr[2] = (byte)redSUM;
  1479.  
  1480.                     // x = 2
  1481.                     for (x = 2; x < width - 1; x++)
  1482.                     {
  1483.                         dataPtr = dataPtrred + y * m.widthStep + x * nChan;
  1484.  
  1485.                         Iblue += 2 * (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[0] - 2 * (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[0];
  1486.                         Igreen += 2 * (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[1] - 2 * (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[1];
  1487.                         Ired += 2 * (dataPtrStatic + y * m.widthStep + (x + 1) * nChan)[2] - 2 * (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[2];
  1488.  
  1489.                         Iblue += (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[0] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 2) * nChan)[0];
  1490.                         Igreen += (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[1] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 2) * nChan)[1];
  1491.                         Ired += (dataPtrStatic + (y - 1) * m.widthStep + (x + 1) * nChan)[2] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 2) * nChan)[2];
  1492.  
  1493.                         blueSUM = (float)Math.Round(Iblue / 9);
  1494.                         greenSUM = (float)Math.Round(Igreen / 9);
  1495.                         redSUM = (float)Math.Round(Ired / 9);
  1496.  
  1497.                         if (blueSUM > 255) blueSUM = 255;
  1498.                         else if (blueSUM < 0) blueSUM = 0;
  1499.  
  1500.                         if (greenSUM > 255) greenSUM = 255;
  1501.                         else if (greenSUM < 0) greenSUM = 0;
  1502.  
  1503.                         if (redSUM > 255) redSUM = 255;
  1504.                         else if (redSUM < 0) redSUM = 0;
  1505.  
  1506.                         dataPtr[0] = (byte)blueSUM;
  1507.                         dataPtr[1] = (byte)greenSUM;
  1508.                         dataPtr[2] = (byte)redSUM;
  1509.                     }
  1510.  
  1511.                     // x = width - 1
  1512.                     dataPtr = dataPtrred + y * m.widthStep + x * nChan;
  1513.  
  1514.                     Iblue += 2 * (dataPtrStatic + y * m.widthStep + x * nChan)[0] - 2 * (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[0];
  1515.                     Igreen += 2 * (dataPtrStatic + y * m.widthStep + x * nChan)[1] - 2 * (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[1];
  1516.                     Ired += 2 * (dataPtrStatic + y * m.widthStep + x * nChan)[2] - 2 * (dataPtrStatic + y * m.widthStep + (x - 2) * nChan)[2];
  1517.  
  1518.                     Iblue += (dataPtrStatic + (y - 1) * m.widthStep + x * nChan)[0] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 2) * nChan)[0];
  1519.                     Igreen += (dataPtrStatic + (y - 1) * m.widthStep + x * nChan)[1] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 2) * nChan)[1];
  1520.                     Ired += (dataPtrStatic + (y - 1) * m.widthStep + x * nChan)[2] - (dataPtrStatic + (y - 1) * m.widthStep + (x - 2) * nChan)[2];
  1521.  
  1522.                     blueSUM = (float)Math.Round(Iblue / 9);
  1523.                     greenSUM = (float)Math.Round(Igreen / 9);
  1524.                     redSUM = (float)Math.Round(Ired / 9);
  1525.  
  1526.                     if (blueSUM > 255) blueSUM = 255;
  1527.                     else if (blueSUM < 0) blueSUM = 0;
  1528.  
  1529.                     if (greenSUM > 255) greenSUM = 255;
  1530.                     else if (greenSUM < 0) greenSUM = 0;
  1531.  
  1532.                     if (redSUM > 255) redSUM = 255;
  1533.                     else if (redSUM < 0) redSUM = 0;
  1534.  
  1535.                     dataPtr[0] = (byte)blueSUM;
  1536.                     dataPtr[1] = (byte)greenSUM;
  1537.                     dataPtr[2] = (byte)redSUM;
  1538.                 }
  1539.             }
  1540.         } // End of Mean Solution B
  1541.  
  1542.         // Non Uniform Corrente -> Faster but with more errors
  1543.         public static void NonUniform_Marco(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy, float[,] matrix, float matrixWeight)
  1544.         {
  1545.             unsafe
  1546.             {
  1547.                 MIplImage m = imgCopy.MIplImage;
  1548.                 MIplImage d = img.MIplImage;
  1549.                 byte* dataPtr_org = (byte*)m.imageData.ToPointer(); // Pointer to the original image
  1550.                 byte* dataPtr = (byte*)d.imageData.ToPointer();   // Pointer to the final image
  1551.                 byte* centerPx, o_centerPx;
  1552.  
  1553.                 int w = img.Width;
  1554.                 int h = img.Height;
  1555.                 int nChan = m.nChannels; // number of channels - 3
  1556.                 int widthStep = m.widthStep;
  1557.                 int x, y;
  1558.                 double[] sum = new double[3];
  1559.                 double[] w_sum = new double[3];
  1560.  
  1561.                 if (nChan == 3) // image in RGB
  1562.                 {
  1563.                     // *** Corners ***
  1564.                     // Top Left
  1565.                     x = 0; y = 0;
  1566.                     o_centerPx = dataPtr_org + y * widthStep + x * nChan;
  1567.                     centerPx = dataPtr + y * widthStep + x * nChan;
  1568.  
  1569.                     sum[0] = (o_centerPx)[0] * (matrix[1, 1] + matrix[0, 0] + matrix[0, 1] + matrix[1, 0])
  1570.                             + (o_centerPx + nChan)[0] * (matrix[2, 1] + matrix[2, 0])
  1571.                             + (o_centerPx + widthStep)[0] * (matrix[1, 2] + matrix[0, 2])
  1572.                             + (o_centerPx + widthStep + nChan)[0] * (matrix[2, 2]);
  1573.  
  1574.                     sum[1] = (o_centerPx)[1] * (matrix[1, 1] + matrix[0, 0] + matrix[0, 1] + matrix[1, 0])
  1575.                             + (o_centerPx + nChan)[1] * (matrix[2, 1] + matrix[2, 0])
  1576.                             + (o_centerPx + widthStep)[1] * (matrix[1, 2] + matrix[0, 2])
  1577.                             + (o_centerPx + widthStep + nChan)[1] * (matrix[2, 2]);
  1578.  
  1579.                     sum[2] = (o_centerPx)[2] * (matrix[1, 1] + matrix[0, 0] + matrix[0, 1] + matrix[1, 0])
  1580.                             + (o_centerPx + nChan)[2] * (matrix[2, 1] + matrix[2, 0])
  1581.                             + (o_centerPx + widthStep)[2] * (matrix[1, 2] + matrix[0, 2])
  1582.                             + (o_centerPx + widthStep + nChan)[2] * (matrix[2, 2]);
  1583.  
  1584.                     w_sum[0] = Math.Round(sum[0] / matrixWeight);
  1585.                     w_sum[1] = Math.Round(sum[1] / matrixWeight);
  1586.                     w_sum[2] = Math.Round(sum[2] / matrixWeight);
  1587.  
  1588.                     centerPx[0] = (byte)(w_sum[0] > 255 ? 255 : (w_sum[0] < 0) ? 0 : w_sum[0]);
  1589.                     centerPx[1] = (byte)(w_sum[1] > 255 ? 255 : (w_sum[1] < 0) ? 0 : w_sum[1]);
  1590.                     centerPx[2] = (byte)(w_sum[2] > 255 ? 255 : (w_sum[2] < 0) ? 0 : w_sum[2]);
  1591.  
  1592.                     // Top Right
  1593.                     x = w - 1; y = 0;
  1594.                     o_centerPx = dataPtr_org + y * widthStep + x * nChan;
  1595.                     centerPx = dataPtr + y * widthStep + x * nChan;
  1596.  
  1597.                     sum[0] = (o_centerPx)[0] * (matrix[2, 2] + matrix[1, 1] + matrix[1, 2] + matrix[2, 1])
  1598.                             + (o_centerPx - nChan)[0] * (matrix[0, 1] + matrix[0, 0])
  1599.                             + (o_centerPx + widthStep)[0] * (matrix[1, 2] + matrix[2, 2])
  1600.                             + (o_centerPx + widthStep - nChan)[0] * (matrix[0, 2]);
  1601.  
  1602.                     sum[1] = (o_centerPx)[1] * (matrix[2, 2] + matrix[1, 1] + matrix[1, 2] + matrix[2, 1])
  1603.                             + (o_centerPx - nChan)[1] * (matrix[0, 1] + matrix[0, 0])
  1604.                             + (o_centerPx + widthStep)[1] * (matrix[1, 2] + matrix[2, 2])
  1605.                             + (o_centerPx + widthStep - nChan)[1] * (matrix[0, 2]);
  1606.  
  1607.                     sum[2] = (o_centerPx)[2] * (matrix[2, 2] + matrix[1, 1] + matrix[1, 2] + matrix[2, 1])
  1608.                             + (o_centerPx - nChan)[2] * (matrix[0, 1] + matrix[0, 0])
  1609.                             + (o_centerPx + widthStep)[2] * (matrix[1, 2] + matrix[2, 2])
  1610.                             + (o_centerPx + widthStep - nChan)[2] * (matrix[0, 2]);
  1611.  
  1612.                     w_sum[0] = Math.Round(sum[0] / matrixWeight);
  1613.                     w_sum[1] = Math.Round(sum[1] / matrixWeight);
  1614.                     w_sum[2] = Math.Round(sum[2] / matrixWeight);
  1615.  
  1616.                     centerPx[0] = (byte)(w_sum[0] > 255 ? 255 : (w_sum[0] < 0) ? 0 : w_sum[0]);
  1617.                     centerPx[1] = (byte)(w_sum[1] > 255 ? 255 : (w_sum[1] < 0) ? 0 : w_sum[1]);
  1618.                     centerPx[2] = (byte)(w_sum[2] > 255 ? 255 : (w_sum[2] < 0) ? 0 : w_sum[2]);
  1619.  
  1620.                     // Bottom Left
  1621.                     x = 0; y = h - 1;
  1622.                     o_centerPx = dataPtr_org + y * widthStep + x * nChan;
  1623.                     centerPx = dataPtr + y * widthStep + x * nChan;
  1624.  
  1625.                     sum[0] = (o_centerPx)[0] * (matrix[1, 1] + matrix[2, 2] + matrix[2, 1] + matrix[1, 2])
  1626.                             + (o_centerPx + nChan)[0] * (matrix[2, 1] + matrix[2, 2])
  1627.                             + (o_centerPx - widthStep)[0] * (matrix[1, 0] + matrix[0, 0])
  1628.                             + (o_centerPx - widthStep + nChan)[0] * matrix[2, 0];
  1629.  
  1630.                     sum[1] = (o_centerPx)[1] * (matrix[1, 1] + matrix[2, 2] + matrix[2, 1] + matrix[1, 2])
  1631.                             + (o_centerPx + nChan)[1] * (matrix[2, 1] + matrix[2, 2])
  1632.                             + (o_centerPx - widthStep)[1] * (matrix[1, 0] + matrix[0, 0])
  1633.                             + (o_centerPx - widthStep + nChan)[1] * matrix[0, 2];
  1634.  
  1635.                     sum[2] = (o_centerPx)[2] * (matrix[1, 1] + matrix[2, 2] + matrix[2, 1] + matrix[1, 2])
  1636.                             + (o_centerPx + nChan)[2] * (matrix[2, 1] + matrix[2, 2])
  1637.                             + (o_centerPx - widthStep)[2] * (matrix[1, 0] + matrix[0, 0])
  1638.                             + (o_centerPx - widthStep + nChan)[2] * matrix[2, 0];
  1639.  
  1640.                     w_sum[0] = Math.Round(sum[0] / matrixWeight);
  1641.                     w_sum[1] = Math.Round(sum[1] / matrixWeight);
  1642.                     w_sum[2] = Math.Round(sum[2] / matrixWeight);
  1643.  
  1644.                     centerPx[0] = (byte)(w_sum[0] > 255 ? 255 : (w_sum[0] < 0) ? 0 : w_sum[0]);
  1645.                     centerPx[1] = (byte)(w_sum[1] > 255 ? 255 : (w_sum[1] < 0) ? 0 : w_sum[1]);
  1646.                     centerPx[2] = (byte)(w_sum[2] > 255 ? 255 : (w_sum[2] < 0) ? 0 : w_sum[2]);
  1647.  
  1648.                     // Bottom Right
  1649.                     x = w - 1; y = h - 1;
  1650.                     o_centerPx = dataPtr_org + y * widthStep + x * nChan;
  1651.                     centerPx = dataPtr + y * widthStep + x * nChan;
  1652.  
  1653.                     sum[0] = (o_centerPx)[0] * (matrix[1, 1] + matrix[2, 1] + matrix[1, 2] + matrix[2, 2])
  1654.                             + (o_centerPx - nChan)[0] * (matrix[0, 1] + matrix[0, 2])
  1655.                             + (o_centerPx - widthStep)[0] * (matrix[1, 0] + matrix[2, 0])
  1656.                             + (o_centerPx - widthStep - nChan)[0] * matrix[0, 0];
  1657.  
  1658.                     sum[1] = (o_centerPx)[1] * (matrix[1, 1] + matrix[2, 1] + matrix[1, 2] + matrix[2, 2])
  1659.                             + (o_centerPx - nChan)[1] * (matrix[0, 1] + matrix[0, 2])
  1660.                             + (o_centerPx - widthStep)[1] * (matrix[1, 0] + matrix[2, 0])
  1661.                             + (o_centerPx - widthStep - nChan)[1] * matrix[0, 0];
  1662.  
  1663.                     sum[2] = (o_centerPx)[2] * (matrix[1, 1] + matrix[2, 1] + matrix[1, 2] + matrix[2, 2])
  1664.                             + (o_centerPx - nChan)[2] * (matrix[0, 1] + matrix[0, 2])
  1665.                             + (o_centerPx - widthStep)[2] * (matrix[1, 0] + matrix[2, 0])
  1666.                             + (o_centerPx - widthStep - nChan)[2] * matrix[0, 0];
  1667.  
  1668.                     w_sum[0] = Math.Round(sum[0] / matrixWeight);
  1669.                     w_sum[1] = Math.Round(sum[1] / matrixWeight);
  1670.                     w_sum[2] = Math.Round(sum[2] / matrixWeight);
  1671.  
  1672.                     centerPx[0] = (byte)(w_sum[0] > 255 ? 255 : (w_sum[0] < 0) ? 0 : w_sum[0]);
  1673.                     centerPx[1] = (byte)(w_sum[1] > 255 ? 255 : (w_sum[1] < 0) ? 0 : w_sum[1]);
  1674.                     centerPx[2] = (byte)(w_sum[2] > 255 ? 255 : (w_sum[2] < 0) ? 0 : w_sum[2]);
  1675.  
  1676.                     // *** BORDERS ***
  1677.                     // Left
  1678.                     for (y = 1, x = 0; y < h - 1; y++)
  1679.                     {
  1680.                         o_centerPx = dataPtr_org + y * widthStep + x * nChan;
  1681.                         centerPx = dataPtr + y * widthStep + x * nChan;
  1682.  
  1683.                         sum[0] = (o_centerPx - widthStep)[0] * (matrix[0, 0] + matrix[1, 0])
  1684.                                 + (o_centerPx - widthStep + nChan)[0] * (matrix[2, 0])
  1685.                                 + (o_centerPx)[0] * (matrix[0, 1] + matrix[1, 1])
  1686.                                 + (o_centerPx + nChan)[0] * (matrix[2, 1])
  1687.                                 + (o_centerPx + widthStep)[0] * (matrix[0, 2] + matrix[2, 2])
  1688.                                 + (o_centerPx + widthStep + nChan)[0] * (matrix[2, 2]);
  1689.  
  1690.                         sum[1] = (o_centerPx - widthStep)[1] * (matrix[0, 0] + matrix[1, 0])
  1691.                                 + (o_centerPx - widthStep + nChan)[1] * (matrix[2, 0])
  1692.                                 + (o_centerPx)[1] * (matrix[0, 1] + matrix[1, 1])
  1693.                                 + (o_centerPx + nChan)[1] * (matrix[2, 1])
  1694.                                 + (o_centerPx + widthStep)[1] * (matrix[0, 2] + matrix[2, 2])
  1695.                                 + (o_centerPx + widthStep + nChan)[1] * (matrix[2, 2]);
  1696.  
  1697.                         sum[2] = (o_centerPx - widthStep)[2] * (matrix[0, 0] + matrix[1, 0])
  1698.                                 + (o_centerPx - widthStep + nChan)[2] * (matrix[2, 0])
  1699.                                 + (o_centerPx)[2] * (matrix[0, 1] + matrix[1, 1])
  1700.                                 + (o_centerPx + nChan)[2] * (matrix[2, 1])
  1701.                                 + (o_centerPx + widthStep)[2] * (matrix[0, 2] + matrix[2, 2])
  1702.                                 + (o_centerPx + widthStep + nChan)[2] * (matrix[2, 2]);
  1703.  
  1704.                         w_sum[0] = Math.Round(sum[0] / matrixWeight);
  1705.                         w_sum[1] = Math.Round(sum[1] / matrixWeight);
  1706.                         w_sum[2] = Math.Round(sum[2] / matrixWeight);
  1707.  
  1708.                         centerPx[0] = (byte)(w_sum[0] > 255 ? 255 : (w_sum[0] < 0) ? 0 : w_sum[0]);
  1709.                         centerPx[1] = (byte)(w_sum[1] > 255 ? 255 : (w_sum[1] < 0) ? 0 : w_sum[1]);
  1710.                         centerPx[2] = (byte)(w_sum[2] > 255 ? 255 : (w_sum[2] < 0) ? 0 : w_sum[2]);
  1711.                     }
  1712.  
  1713.                     // Right
  1714.                     for (y = 1, x = w - 1; y < h - 1; y++)
  1715.                     {
  1716.                         o_centerPx = dataPtr_org + y * widthStep + x * nChan;
  1717.                         centerPx = dataPtr + y * widthStep + x * nChan;
  1718.  
  1719.                         sum[0] = (o_centerPx - widthStep)[0] * (matrix[0, 1] + matrix[2, 0])
  1720.                                 + (o_centerPx - widthStep - nChan)[0] * (matrix[0, 0])
  1721.                                 + (o_centerPx)[0] * (matrix[1, 1] + matrix[2, 1])
  1722.                                 + (o_centerPx - nChan)[0] * (matrix[0, 1])
  1723.                                 + (o_centerPx + widthStep)[0] * (matrix[1, 2] + matrix[2, 2])
  1724.                                 + (o_centerPx + widthStep - nChan)[0] * (matrix[0, 2]);
  1725.  
  1726.                         sum[1] = (o_centerPx - widthStep)[1] * (matrix[0, 1] + matrix[2, 0])
  1727.                                 + (o_centerPx - widthStep - nChan)[1] * (matrix[0, 0])
  1728.                                 + (o_centerPx)[1] * (matrix[1, 1] + matrix[2, 1])
  1729.                                 + (o_centerPx - nChan)[1] * (matrix[0, 1])
  1730.                                 + (o_centerPx + widthStep)[1] * (matrix[1, 2] + matrix[2, 2])
  1731.                                 + (o_centerPx + widthStep - nChan)[1] * (matrix[0, 2]);
  1732.  
  1733.                         sum[2] = (o_centerPx - widthStep)[2] * (matrix[0, 1] + matrix[2, 0])
  1734.                                 + (o_centerPx - widthStep - nChan)[2] * (matrix[0, 0])
  1735.                                 + (o_centerPx)[2] * (matrix[1, 1] + matrix[2, 1])
  1736.                                 + (o_centerPx - nChan)[2] * (matrix[0, 1])
  1737.                                 + (o_centerPx + widthStep)[2] * (matrix[1, 2] + matrix[2, 2])
  1738.                                 + (o_centerPx + widthStep - nChan)[2] * (matrix[0, 2]);
  1739.  
  1740.                         w_sum[0] = Math.Round(sum[0] / matrixWeight);
  1741.                         w_sum[1] = Math.Round(sum[1] / matrixWeight);
  1742.                         w_sum[2] = Math.Round(sum[2] / matrixWeight);
  1743.  
  1744.                         centerPx[0] = (byte)(w_sum[0] > 255 ? 255 : (w_sum[0] < 0) ? 0 : w_sum[0]);
  1745.                         centerPx[1] = (byte)(w_sum[1] > 255 ? 255 : (w_sum[1] < 0) ? 0 : w_sum[1]);
  1746.                         centerPx[2] = (byte)(w_sum[2] > 255 ? 255 : (w_sum[2] < 0) ? 0 : w_sum[2]);
  1747.                     }
  1748.  
  1749.                     // Top
  1750.                     for (x = 1, y = 0; x < w - 1; x++)
  1751.                     {
  1752.                         o_centerPx = dataPtr_org + y * widthStep + x * nChan;
  1753.                         centerPx = dataPtr + y * widthStep + x * nChan;
  1754.  
  1755.                         sum[0] = (o_centerPx - nChan)[0] * (matrix[0, 0] + matrix[0, 1])
  1756.                                 + (o_centerPx)[0] * (matrix[1, 1] + matrix[1, 0])
  1757.                                 + (o_centerPx + nChan)[0] * (matrix[2, 1] + matrix[2, 0])
  1758.                                 + (o_centerPx + widthStep - nChan)[0] * (matrix[0, 2])
  1759.                                 + (o_centerPx + widthStep)[0] * (matrix[1, 2])
  1760.                                 + (o_centerPx + widthStep + nChan)[0] * (matrix[2, 2]);
  1761.  
  1762.                         sum[1] = (o_centerPx - nChan)[1] * (matrix[0, 0] + matrix[0, 1])
  1763.                                 + (o_centerPx)[1] * (matrix[1, 1] + matrix[1, 0])
  1764.                                 + (o_centerPx + nChan)[1] * (matrix[2, 1] + matrix[2, 0])
  1765.                                 + (o_centerPx + widthStep - nChan)[1] * (matrix[0, 2])
  1766.                                 + (o_centerPx + widthStep)[1] * (matrix[1, 2])
  1767.                                 + (o_centerPx + widthStep + nChan)[1] * (matrix[2, 2]);
  1768.  
  1769.                         sum[2] = (o_centerPx - nChan)[2] * (matrix[0, 0] + matrix[0, 1])
  1770.                                 + (o_centerPx)[2] * (matrix[1, 1] + matrix[1, 0])
  1771.                                 + (o_centerPx + nChan)[2] * (matrix[2, 1] + matrix[2, 0])
  1772.                                 + (o_centerPx + widthStep - nChan)[2] * (matrix[0, 2])
  1773.                                 + (o_centerPx + widthStep)[2] * (matrix[1, 2])
  1774.                                 + (o_centerPx + widthStep + nChan)[2] * (matrix[2, 2]);
  1775.  
  1776.                         w_sum[0] = Math.Round(sum[0] / matrixWeight);
  1777.                         w_sum[1] = Math.Round(sum[1] / matrixWeight);
  1778.                         w_sum[2] = Math.Round(sum[2] / matrixWeight);
  1779.  
  1780.                         centerPx[0] = (byte)(w_sum[0] > 255 ? 255 : (w_sum[0] < 0) ? 0 : w_sum[0]);
  1781.                         centerPx[1] = (byte)(w_sum[1] > 255 ? 255 : (w_sum[1] < 0) ? 0 : w_sum[1]);
  1782.                         centerPx[2] = (byte)(w_sum[2] > 255 ? 255 : (w_sum[2] < 0) ? 0 : w_sum[2]);
  1783.                     }
  1784.  
  1785.                     // Bottom
  1786.                     for (x = 1, y = h - 1; x < w - 1; x++)
  1787.                     {
  1788.                         o_centerPx = dataPtr_org + y * widthStep + x * nChan;
  1789.                         centerPx = dataPtr + y * widthStep + x * nChan;
  1790.  
  1791.                         sum[0] = (o_centerPx - widthStep - nChan)[0] * (matrix[0, 0])
  1792.                                 + (o_centerPx - widthStep)[0] * (matrix[1, 0])
  1793.                                 + (o_centerPx - widthStep + nChan)[0] * (matrix[2, 0])
  1794.                                 + (o_centerPx - nChan)[0] * (matrix[0, 1] + matrix[0, 2])
  1795.                                 + (o_centerPx)[0] * (matrix[1, 1] + matrix[1, 2])
  1796.                                 + (o_centerPx + nChan)[0] * (matrix[2, 1] + matrix[2, 2]);
  1797.  
  1798.                         sum[1] = (o_centerPx - widthStep - nChan)[1] * (matrix[0, 0])
  1799.                                 + (o_centerPx - widthStep)[1] * (matrix[1, 0])
  1800.                                 + (o_centerPx - widthStep + nChan)[1] * (matrix[2, 0])
  1801.                                 + (o_centerPx - nChan)[1] * (matrix[0, 1] + matrix[0, 2])
  1802.                                 + (o_centerPx)[1] * (matrix[1, 1] + matrix[1, 2])
  1803.                                 + (o_centerPx + nChan)[1] * (matrix[2, 1] + matrix[2, 2]);
  1804.  
  1805.                         sum[2] = (o_centerPx - widthStep - nChan)[2] * (matrix[0, 0])
  1806.                                 + (o_centerPx - widthStep)[2] * (matrix[1, 0])
  1807.                                 + (o_centerPx - widthStep + nChan)[2] * (matrix[2, 0])
  1808.                                 + (o_centerPx - nChan)[2] * (matrix[0, 1] + matrix[0, 2])
  1809.                                 + (o_centerPx)[2] * (matrix[1, 1] + matrix[1, 2])
  1810.                                 + (o_centerPx + nChan)[2] * (matrix[2, 1] + matrix[2, 2]);
  1811.  
  1812.                         w_sum[0] = Math.Round(sum[0] / matrixWeight);
  1813.                         w_sum[1] = Math.Round(sum[1] / matrixWeight);
  1814.                         w_sum[2] = Math.Round(sum[2] / matrixWeight);
  1815.  
  1816.                         centerPx[0] = (byte)(w_sum[0] > 255 ? 255 : (w_sum[0] < 0) ? 0 : w_sum[0]);
  1817.                         centerPx[1] = (byte)(w_sum[1] > 255 ? 255 : (w_sum[1] < 0) ? 0 : w_sum[1]);
  1818.                         centerPx[2] = (byte)(w_sum[2] > 255 ? 255 : (w_sum[2] < 0) ? 0 : w_sum[2]);
  1819.                     }
  1820.  
  1821.                     // *** CORE ***
  1822.                     for (y = 1; y < h - 1; y++)
  1823.                     {
  1824.                         for (x = 1; x < w - 1; x++)
  1825.                         {
  1826.                             o_centerPx = dataPtr_org + y * widthStep + x * nChan;
  1827.                             centerPx = dataPtr + y * widthStep + x * nChan;
  1828.  
  1829.                             sum[0] = (o_centerPx - widthStep - nChan)[0] * matrix[0, 0]
  1830.                                     + (o_centerPx - widthStep)[0] * matrix[1, 0]
  1831.                                     + (o_centerPx - widthStep + nChan)[0] * matrix[2, 0]
  1832.                                     + (o_centerPx - nChan)[0] * matrix[0, 1]
  1833.                                     + (o_centerPx)[0] * matrix[1, 1]
  1834.                                     + (o_centerPx + nChan)[0] * matrix[2, 1]
  1835.                                     + (o_centerPx + widthStep - nChan)[0] * matrix[0, 2]
  1836.                                     + (o_centerPx + widthStep)[0] * matrix[1, 2]
  1837.                                     + (o_centerPx + widthStep + nChan)[0] * matrix[2, 2];
  1838.  
  1839.                             sum[1] = (o_centerPx - widthStep - nChan)[1] * matrix[0, 0]
  1840.                                     + (o_centerPx - widthStep)[1] * matrix[1, 0]
  1841.                                     + (o_centerPx - widthStep + nChan)[1] * matrix[2, 0]
  1842.                                     + (o_centerPx - nChan)[1] * matrix[0, 1]
  1843.                                     + (o_centerPx)[1] * matrix[1, 1]
  1844.                                     + (o_centerPx + nChan)[1] * matrix[2, 1]
  1845.                                     + (o_centerPx + widthStep - nChan)[1] * matrix[0, 2]
  1846.                                     + (o_centerPx + widthStep)[1] * matrix[1, 2]
  1847.                                     + (o_centerPx + widthStep + nChan)[1] * matrix[2, 2];
  1848.  
  1849.                             sum[2] = (o_centerPx - widthStep - nChan)[2] * matrix[0, 0]
  1850.                                     + (o_centerPx - widthStep)[2] * matrix[1, 0]
  1851.                                     + (o_centerPx - widthStep + nChan)[2] * matrix[2, 0]
  1852.                                     + (o_centerPx - nChan)[2] * matrix[0, 1]
  1853.                                     + (o_centerPx)[2] * matrix[1, 1]
  1854.                                     + (o_centerPx + nChan)[2] * matrix[2, 1]
  1855.                                     + (o_centerPx + widthStep - nChan)[2] * matrix[0, 2]
  1856.                                     + (o_centerPx + widthStep)[2] * matrix[1, 2]
  1857.                                     + (o_centerPx + widthStep + nChan)[2] * matrix[2, 2];
  1858.  
  1859.                             w_sum[0] = Math.Round(sum[0] / matrixWeight);
  1860.                             w_sum[1] = Math.Round(sum[1] / matrixWeight);
  1861.                             w_sum[2] = Math.Round(sum[2] / matrixWeight);
  1862.  
  1863.                             centerPx[0] = (byte)(w_sum[0] > 255 ? 255 : (w_sum[0] < 0) ? 0 : w_sum[0]);
  1864.                             centerPx[1] = (byte)(w_sum[1] > 255 ? 255 : (w_sum[1] < 0) ? 0 : w_sum[1]);
  1865.                             centerPx[2] = (byte)(w_sum[2] > 255 ? 255 : (w_sum[2] < 0) ? 0 : w_sum[2]);
  1866.                         }
  1867.                     }
  1868.                 } // End of nChan = 3
  1869.             } // End of Unsafe
  1870.         } // End of Non-Uniform
  1871.  
  1872.         // Non Uniform Nabais -> Slower but with less errors
  1873.         public static void NonUniform(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy, float[,] matrix, float matrixWeight)
  1874.         {
  1875.             unsafe
  1876.             {
  1877.                 // direct access to the image memory(sequencial)
  1878.                 // direcion top left -> bottom right
  1879.                 MIplImage m = img.MIplImage;
  1880.                 MIplImage m1 = imgCopy.MIplImage;
  1881.                 byte* dataPtr = (byte*)m.imageData.ToPointer(); // Pointer to the image
  1882.                 byte* dataPtrref = dataPtr;
  1883.                 byte* auxdataPtr = (byte*)m1.imageData.ToPointer(); // Pointer to the image
  1884.                 byte* dataPtrStatic = auxdataPtr; // Pointer de referência para o início da imagem a editar
  1885.  
  1886.                 int width = img.Width;
  1887.                 int height = img.Height;
  1888.                 int nChan = m.nChannels; // number of channels - 3
  1889.                 int padding = m.widthStep - m.nChannels * m.width; // alinhament bytes (padding)
  1890.                 int x, y, i, j;
  1891.  
  1892.                 float blueSUM = 0, greenSUM = 0, redSUM = 0;
  1893.  
  1894.                 dataPtr += m.widthStep + nChan;
  1895.                 dataPtrStatic += m.widthStep + nChan;
  1896.  
  1897.                 if (nChan == 3)
  1898.                 {
  1899.                     // dentro da imagem, fora as margens+cantos
  1900.                     for (y = 1; y < height - 1; y++)
  1901.                     {
  1902.                         for (x = 1; x < width - 1; x++)
  1903.                         {
  1904.                             blueSUM = 0;
  1905.                             greenSUM = 0;
  1906.                             redSUM = 0;
  1907.  
  1908.                             dataPtr = dataPtrref + y * m.widthStep + x * nChan;
  1909.  
  1910.                             for (i = 0; i < 3; i++)
  1911.                             {
  1912.                                 auxdataPtr = dataPtrStatic + (i - 1) * m.widthStep - nChan;
  1913.                                 for (j = 0; j < 3; j++)
  1914.                                 {
  1915.                                     blueSUM += matrix[i, j] * (auxdataPtr)[0];
  1916.                                     greenSUM += matrix[i, j] * (auxdataPtr)[1];
  1917.                                     redSUM += matrix[i, j] * (auxdataPtr)[2];
  1918.  
  1919.                                     auxdataPtr += nChan;
  1920.                                 }
  1921.                             }
  1922.  
  1923.                             blueSUM = (float)Math.Round(blueSUM / matrixWeight);
  1924.                             greenSUM = (float)Math.Round(greenSUM / matrixWeight);
  1925.                             redSUM = (float)Math.Round(redSUM / matrixWeight);
  1926.  
  1927.                             if (blueSUM > 255) blueSUM = 255;
  1928.                             else if (blueSUM < 0) blueSUM = 0;
  1929.  
  1930.                             if (greenSUM > 255) greenSUM = 255;
  1931.                             else if (greenSUM < 0) greenSUM = 0;
  1932.  
  1933.                             if (redSUM > 255) redSUM = 255;
  1934.                             else if (redSUM < 0) redSUM = 0;
  1935.  
  1936.                             dataPtr[0] = (byte)blueSUM;
  1937.                             dataPtr[1] = (byte)greenSUM;
  1938.                             dataPtr[2] = (byte)redSUM;
  1939.  
  1940.                             dataPtrStatic += nChan;
  1941.                         }
  1942.  
  1943.                         dataPtrStatic += padding + 2 * nChan;
  1944.                     }
  1945.  
  1946.                     // última linha
  1947.                     for (x = 1; x < width - 1; x++)
  1948.                     {
  1949.                         blueSUM = 0;
  1950.                         greenSUM = 0;
  1951.                         redSUM = 0;
  1952.  
  1953.                         dataPtr = dataPtrref + y * m.widthStep + x * nChan;
  1954.                         auxdataPtr = dataPtrStatic - m.widthStep - nChan;
  1955.  
  1956.                         for (i = 0; i < 3; i++)
  1957.                         {
  1958.                             blueSUM += auxdataPtr[0] * matrix[i, 0];
  1959.                             greenSUM += auxdataPtr[1] * matrix[i, 0];
  1960.                             redSUM += auxdataPtr[2] * matrix[i, 0];
  1961.  
  1962.                             auxdataPtr += nChan;
  1963.                         }
  1964.  
  1965.                         auxdataPtr = dataPtrStatic - nChan;
  1966.  
  1967.                         for (i = 0; i < 3; i++)
  1968.                         {
  1969.                             blueSUM += auxdataPtr[0] * (matrix[i, 1] + matrix[i, 2]);
  1970.                             greenSUM += auxdataPtr[1] * (matrix[i, 1] + matrix[i, 2]);
  1971.                             redSUM += auxdataPtr[2] * (matrix[i, 1] + matrix[i, 2]);
  1972.  
  1973.                             auxdataPtr += nChan;
  1974.                         }
  1975.  
  1976.                         blueSUM = (float)Math.Round(blueSUM / matrixWeight);
  1977.                         greenSUM = (float)Math.Round(greenSUM / matrixWeight);
  1978.                         redSUM = (float)Math.Round(redSUM / matrixWeight);
  1979.  
  1980.                         if (blueSUM > 255) blueSUM = 255;
  1981.                         else if (blueSUM < 0) blueSUM = 0;
  1982.  
  1983.                         if (greenSUM > 255) greenSUM = 255;
  1984.                         else if (greenSUM < 0) greenSUM = 0;
  1985.  
  1986.                         if (redSUM > 255) redSUM = 255;
  1987.                         else if (redSUM < 0) redSUM = 0;
  1988.  
  1989.                         dataPtr[0] = (byte)blueSUM;
  1990.                         dataPtr[1] = (byte)greenSUM;
  1991.                         dataPtr[2] = (byte)redSUM;
  1992.  
  1993.                         dataPtrStatic += nChan;
  1994.                     }
  1995.  
  1996.                     dataPtr = dataPtrref + y * m.widthStep + x * nChan;
  1997.                     //canto inferior direito
  1998.                     {
  1999.                         auxdataPtr = dataPtrStatic - m.widthStep - nChan;
  2000.  
  2001.                         blueSUM = auxdataPtr[0] * matrix[0, 0];
  2002.                         greenSUM = auxdataPtr[1] * matrix[0, 0];
  2003.                         redSUM = auxdataPtr[2] * matrix[0, 0];
  2004.  
  2005.                         auxdataPtr += nChan;
  2006.  
  2007.                         blueSUM += auxdataPtr[0] * (matrix[0, 1] + matrix[0, 2]);
  2008.                         greenSUM += auxdataPtr[1] * (matrix[0, 1] + matrix[0, 2]);
  2009.                         redSUM += auxdataPtr[2] * (matrix[0, 1] + matrix[0, 2]);
  2010.  
  2011.                         auxdataPtr = dataPtrStatic - nChan;
  2012.  
  2013.                         blueSUM += auxdataPtr[0] * (matrix[1, 0] + matrix[2, 0]);
  2014.                         greenSUM += auxdataPtr[1] * (matrix[1, 0] + matrix[2, 0]);
  2015.                         redSUM += auxdataPtr[2] * (matrix[1, 0] + matrix[2, 0]);
  2016.  
  2017.                         auxdataPtr += nChan;
  2018.  
  2019.                         blueSUM += auxdataPtr[0] * (matrix[1, 1] + matrix[1, 2] + matrix[2, 1] + matrix[2, 2]);
  2020.                         greenSUM += auxdataPtr[1] * (matrix[1, 1] + matrix[1, 2] + matrix[2, 1] + matrix[2, 2]);
  2021.                         redSUM += auxdataPtr[2] * (matrix[1, 1] + matrix[1, 2] + matrix[2, 1] + matrix[2, 2]);
  2022.  
  2023.                         blueSUM = (float)Math.Round(blueSUM / matrixWeight);
  2024.                         greenSUM = (float)Math.Round(greenSUM / matrixWeight);
  2025.                         redSUM = (float)Math.Round(redSUM / matrixWeight);
  2026.  
  2027.                         if (blueSUM > 255) blueSUM = 255;
  2028.                         else if (blueSUM < 0) blueSUM = 0;
  2029.  
  2030.                         if (greenSUM > 255) greenSUM = 255;
  2031.                         else if (greenSUM < 0) greenSUM = 0;
  2032.  
  2033.                         if (redSUM > 255) redSUM = 255;
  2034.                         else if (redSUM < 0) redSUM = 0;
  2035.  
  2036.                         dataPtr[0] = (byte)blueSUM;
  2037.                         dataPtr[1] = (byte)greenSUM;
  2038.                         dataPtr[2] = (byte)redSUM;
  2039.                     }
  2040.  
  2041.                     dataPtrStatic -= m.widthStep;
  2042.                     //última coluna
  2043.                     for (y = height - 2; y > 0; y--)
  2044.                     {
  2045.                         blueSUM = 0;
  2046.                         greenSUM = 0;
  2047.                         redSUM = 0;
  2048.  
  2049.                         dataPtr = dataPtrref + y * m.widthStep + x * nChan;
  2050.                         auxdataPtr = dataPtrStatic - m.widthStep - nChan;
  2051.  
  2052.                         for (i = 0; i < 3; i++)
  2053.                         {
  2054.                             blueSUM += auxdataPtr[0] * matrix[i, 0];
  2055.                             greenSUM += auxdataPtr[1] * matrix[i, 0];
  2056.                             redSUM += auxdataPtr[2] * matrix[i, 0];
  2057.  
  2058.                             auxdataPtr += m.widthStep;
  2059.                         }
  2060.  
  2061.                         auxdataPtr = dataPtrStatic - m.widthStep;
  2062.  
  2063.                         for (i = 0; i < 3; i++)
  2064.                         {
  2065.                             blueSUM += auxdataPtr[0] * (matrix[i, 1] + matrix[i, 2]);
  2066.                             greenSUM += auxdataPtr[1] * (matrix[i, 1] + matrix[i, 2]);
  2067.                             redSUM += auxdataPtr[2] * (matrix[i, 1] + matrix[i, 2]);
  2068.  
  2069.                             auxdataPtr += m.widthStep;
  2070.                         }
  2071.  
  2072.                         blueSUM = (float)Math.Round(blueSUM / matrixWeight);
  2073.                         greenSUM = (float)Math.Round(greenSUM / matrixWeight);
  2074.                         redSUM = (float)Math.Round(redSUM / matrixWeight);
  2075.  
  2076.                         if (blueSUM > 255) blueSUM = 255;
  2077.                         else if (blueSUM < 0) blueSUM = 0;
  2078.  
  2079.                         if (greenSUM > 255) greenSUM = 255;
  2080.                         else if (greenSUM < 0) greenSUM = 0;
  2081.  
  2082.                         if (redSUM > 255) redSUM = 255;
  2083.                         else if (redSUM < 0) redSUM = 0;
  2084.  
  2085.                         dataPtr[0] = (byte)blueSUM;
  2086.                         dataPtr[1] = (byte)greenSUM;
  2087.                         dataPtr[2] = (byte)redSUM;
  2088.  
  2089.                         dataPtrStatic -= m.widthStep;
  2090.                     }
  2091.  
  2092.                     dataPtr = dataPtrref + y * m.widthStep + x * nChan;
  2093.                     //canto superior direito
  2094.                     {
  2095.                         auxdataPtr = dataPtrStatic - nChan;
  2096.  
  2097.                         blueSUM = auxdataPtr[0] * (matrix[0, 0] + matrix[1, 0]);
  2098.                         greenSUM = auxdataPtr[1] * (matrix[0, 0] + matrix[1, 0]);
  2099.                         redSUM = auxdataPtr[2] * (matrix[0, 0] + matrix[1, 0]);
  2100.  
  2101.                         auxdataPtr += nChan;
  2102.  
  2103.                         blueSUM += auxdataPtr[0] * (matrix[0, 1] + matrix[0, 2] + matrix[1, 1] + matrix[1, 2]);
  2104.                         greenSUM += auxdataPtr[1] * (matrix[0, 1] + matrix[0, 2] + matrix[1, 1] + matrix[1, 2]);
  2105.                         redSUM += auxdataPtr[2] * (matrix[0, 1] + matrix[0, 2] + matrix[1, 1] + matrix[1, 2]);
  2106.  
  2107.                         auxdataPtr += m.widthStep;
  2108.  
  2109.                         blueSUM += auxdataPtr[0] * (matrix[2, 1] + matrix[2, 2]);
  2110.                         greenSUM += auxdataPtr[1] * (matrix[2, 1] + matrix[2, 2]);
  2111.                         redSUM += auxdataPtr[2] * (matrix[2, 1] + matrix[2, 2]);
  2112.  
  2113.                         auxdataPtr -= nChan;
  2114.  
  2115.                         blueSUM += auxdataPtr[0] * matrix[2, 0];
  2116.                         greenSUM += auxdataPtr[1] * matrix[2, 0];
  2117.                         redSUM += auxdataPtr[2] * matrix[2, 0];
  2118.  
  2119.                         blueSUM = (float)Math.Round(blueSUM / matrixWeight);
  2120.                         greenSUM = (float)Math.Round(greenSUM / matrixWeight);
  2121.                         redSUM = (float)Math.Round(redSUM / matrixWeight);
  2122.  
  2123.                         if (blueSUM > 255) blueSUM = 255;
  2124.                         else if (blueSUM < 0) blueSUM = 0;
  2125.  
  2126.                         if (greenSUM > 255) greenSUM = 255;
  2127.                         else if (greenSUM < 0) greenSUM = 0;
  2128.  
  2129.                         if (redSUM > 255) redSUM = 255;
  2130.                         else if (redSUM < 0) redSUM = 0;
  2131.  
  2132.                         dataPtr[0] = (byte)blueSUM;
  2133.                         dataPtr[1] = (byte)greenSUM;
  2134.                         dataPtr[2] = (byte)redSUM;
  2135.                     }
  2136.  
  2137.                     dataPtrStatic -= nChan;
  2138.                     //primeira linha
  2139.                     for (x = width - 2; x > 0; x--)
  2140.                     {
  2141.                         blueSUM = 0;
  2142.                         greenSUM = 0;
  2143.                         redSUM = 0;
  2144.  
  2145.                         auxdataPtr = dataPtrStatic - nChan;
  2146.                         dataPtr = dataPtrref + y * m.widthStep + x * nChan;
  2147.  
  2148.                         for (i = 0; i < 3; i++)
  2149.                         {
  2150.                             blueSUM += auxdataPtr[0] * (matrix[0, i] + matrix[1, i]);
  2151.                             greenSUM += auxdataPtr[1] * (matrix[0, i] + matrix[1, i]);
  2152.                             redSUM += auxdataPtr[2] * (matrix[0, i] + matrix[1, i]);
  2153.  
  2154.                             auxdataPtr += nChan;
  2155.                         }
  2156.  
  2157.                         auxdataPtr = dataPtrStatic + m.widthStep - nChan;
  2158.  
  2159.                         for (i = 0; i < 3; i++)
  2160.                         {
  2161.                             blueSUM += auxdataPtr[0] * matrix[2, i];
  2162.                             greenSUM += auxdataPtr[1] * matrix[2, i];
  2163.                             redSUM += auxdataPtr[2] * matrix[2, i];
  2164.  
  2165.                             auxdataPtr += nChan;
  2166.                         }
  2167.  
  2168.                         blueSUM = (float)Math.Round(blueSUM / matrixWeight);
  2169.                         greenSUM = (float)Math.Round(greenSUM / matrixWeight);
  2170.                         redSUM = (float)Math.Round(redSUM / matrixWeight);
  2171.  
  2172.                         if (blueSUM > 255) blueSUM = 255;
  2173.                         else if (blueSUM < 0) blueSUM = 0;
  2174.  
  2175.                         if (greenSUM > 255) greenSUM = 255;
  2176.                         else if (greenSUM < 0) greenSUM = 0;
  2177.  
  2178.                         if (redSUM > 255) redSUM = 255;
  2179.                         else if (redSUM < 0) redSUM = 0;
  2180.  
  2181.                         dataPtr[0] = (byte)blueSUM;
  2182.                         dataPtr[1] = (byte)greenSUM;
  2183.                         dataPtr[2] = (byte)redSUM;
  2184.  
  2185.                         dataPtrStatic -= nChan;
  2186.                     }
  2187.  
  2188.                     dataPtr = dataPtrref + y * m.widthStep + x * nChan;
  2189.                     //canto superior esquerdo
  2190.                     {
  2191.                         auxdataPtr = dataPtrStatic;
  2192.  
  2193.                         blueSUM = auxdataPtr[0] * (matrix[0, 0] + matrix[0, 1] + matrix[1, 0] + matrix[1, 1]);
  2194.                         greenSUM = auxdataPtr[1] * (matrix[0, 0] + matrix[0, 1] + matrix[1, 0] + matrix[1, 1]);
  2195.                         redSUM = auxdataPtr[2] * (matrix[0, 0] + matrix[0, 1] + matrix[1, 0] + matrix[1, 1]);
  2196.  
  2197.                         auxdataPtr += nChan;
  2198.  
  2199.                         blueSUM = auxdataPtr[0] * (matrix[0, 2] + matrix[1, 2]);
  2200.                         greenSUM = auxdataPtr[1] * (matrix[0, 2] + matrix[1, 2]);
  2201.                         redSUM = auxdataPtr[2] * (matrix[0, 2] + matrix[1, 2]);
  2202.  
  2203.                         auxdataPtr = dataPtrStatic + m.widthStep;
  2204.  
  2205.                         blueSUM = auxdataPtr[0] * (matrix[2, 0] + matrix[2, 1]);
  2206.                         greenSUM = auxdataPtr[1] * (matrix[2, 0] + matrix[2, 1]);
  2207.                         redSUM = auxdataPtr[2] * (matrix[2, 0] + matrix[2, 1]);
  2208.  
  2209.                         auxdataPtr += nChan;
  2210.  
  2211.                         blueSUM = auxdataPtr[0] * matrix[2, 2];
  2212.                         greenSUM = auxdataPtr[1] * matrix[2, 2];
  2213.                         redSUM = auxdataPtr[2] * matrix[2, 2];
  2214.  
  2215.                         blueSUM = (float)Math.Round(blueSUM / matrixWeight);
  2216.                         greenSUM = (float)Math.Round(greenSUM / matrixWeight);
  2217.                         redSUM = (float)Math.Round(redSUM / matrixWeight);
  2218.  
  2219.                         if (blueSUM > 255) blueSUM = 255;
  2220.                         else if (blueSUM < 0) blueSUM = 0;
  2221.  
  2222.                         if (greenSUM > 255) greenSUM = 255;
  2223.                         else if (greenSUM < 0) greenSUM = 0;
  2224.  
  2225.                         if (redSUM > 255) redSUM = 255;
  2226.                         else if (redSUM < 0) redSUM = 0;
  2227.  
  2228.                         dataPtr[0] = (byte)blueSUM;
  2229.                         dataPtr[1] = (byte)greenSUM;
  2230.                         dataPtr[2] = (byte)redSUM;
  2231.                     }
  2232.  
  2233.                     dataPtrStatic += m.widthStep;
  2234.                     //primeira coluna
  2235.                     for (y = 1; y < height - 1; y++)
  2236.                     {
  2237.                         blueSUM = 0;
  2238.                         greenSUM = 0;
  2239.                         redSUM = 0;
  2240.  
  2241.                         dataPtr = dataPtrref + y * m.widthStep + x * nChan;
  2242.                         auxdataPtr = dataPtrStatic - m.widthStep;
  2243.  
  2244.                         for (i = 0; i < 3; i++)
  2245.                         {
  2246.                             blueSUM += auxdataPtr[0] * (matrix[i, 0] + matrix[i, 1]);
  2247.                             greenSUM += auxdataPtr[1] * (matrix[i, 0] + matrix[i, 1]);
  2248.                             redSUM += auxdataPtr[2] * (matrix[i, 0] + matrix[i, 1]);
  2249.  
  2250.                             auxdataPtr += m.widthStep;
  2251.                         }
  2252.  
  2253.                         auxdataPtr = dataPtrStatic - m.widthStep + nChan;
  2254.  
  2255.                         for (i = 0; i < 3; i++)
  2256.                         {
  2257.                             blueSUM += auxdataPtr[0] * matrix[i, 2];
  2258.                             greenSUM += auxdataPtr[1] * matrix[i, 2];
  2259.                             redSUM += auxdataPtr[2] * matrix[i, 2];
  2260.  
  2261.                             auxdataPtr += m.widthStep;
  2262.                         }
  2263.  
  2264.                         blueSUM = (float)Math.Round(blueSUM / matrixWeight);
  2265.                         greenSUM = (float)Math.Round(greenSUM / matrixWeight);
  2266.                         redSUM = (float)Math.Round(redSUM / matrixWeight);
  2267.  
  2268.                         if (blueSUM > 255) blueSUM = 255;
  2269.                         else if (blueSUM < 0) blueSUM = 0;
  2270.  
  2271.                         if (greenSUM > 255) greenSUM = 255;
  2272.                         else if (greenSUM < 0) greenSUM = 0;
  2273.  
  2274.                         if (redSUM > 255) redSUM = 255;
  2275.                         else if (redSUM < 0) redSUM = 0;
  2276.  
  2277.                         dataPtr[0] = (byte)blueSUM;
  2278.                         dataPtr[1] = (byte)greenSUM;
  2279.                         dataPtr[2] = (byte)redSUM;
  2280.  
  2281.                         dataPtrStatic += m.widthStep;
  2282.                     }
  2283.  
  2284.                     dataPtr = dataPtrref + y * m.widthStep + x * nChan;
  2285.                     //canto inferior esquerdo
  2286.                     {
  2287.                         auxdataPtr = dataPtrStatic - m.widthStep;
  2288.  
  2289.                         blueSUM = auxdataPtr[0] * (matrix[0, 0] + matrix[0, 1]);
  2290.                         greenSUM = auxdataPtr[1] * (matrix[0, 0] + matrix[0, 1]);
  2291.                         redSUM = auxdataPtr[2] * (matrix[0, 0] + matrix[0, 1]);
  2292.  
  2293.                         auxdataPtr += nChan;
  2294.  
  2295.                         blueSUM += auxdataPtr[0] * matrix[2, 2];
  2296.                         greenSUM += auxdataPtr[1] * matrix[2, 2];
  2297.                         redSUM += auxdataPtr[2] * matrix[2, 2];
  2298.  
  2299.                         auxdataPtr = dataPtrStatic;
  2300.  
  2301.                         blueSUM += auxdataPtr[0] * (matrix[1, 0] + matrix[1, 1] + matrix[2, 0] + matrix[2, 1]);
  2302.                         greenSUM += auxdataPtr[1] * (matrix[1, 0] + matrix[1, 1] + matrix[2, 0] + matrix[2, 1]);
  2303.                         redSUM += auxdataPtr[2] * (matrix[1, 0] + matrix[1, 1] + matrix[2, 0] + matrix[2, 1]);
  2304.  
  2305.                         auxdataPtr += nChan;
  2306.  
  2307.                         blueSUM += auxdataPtr[0] * (matrix[1, 2] + matrix[2, 2]);
  2308.                         greenSUM += auxdataPtr[1] * (matrix[1, 2] + matrix[2, 2]);
  2309.                         redSUM += auxdataPtr[2] * (matrix[1, 2] + matrix[2, 2]);
  2310.  
  2311.                         blueSUM = (float)Math.Round(blueSUM / matrixWeight);
  2312.                         greenSUM = (float)Math.Round(greenSUM / matrixWeight);
  2313.                         redSUM = (float)Math.Round(redSUM / matrixWeight);
  2314.  
  2315.                         if (blueSUM > 255) blueSUM = 255;
  2316.                         else if (blueSUM < 0) blueSUM = 0;
  2317.  
  2318.                         if (greenSUM > 255) greenSUM = 255;
  2319.                         else if (greenSUM < 0) greenSUM = 0;
  2320.  
  2321.                         if (redSUM > 255) redSUM = 255;
  2322.                         else if (redSUM < 0) redSUM = 0;
  2323.  
  2324.                         dataPtr[0] = (byte)blueSUM;
  2325.                         dataPtr[1] = (byte)greenSUM;
  2326.                         dataPtr[2] = (byte)redSUM;
  2327.                     }
  2328.                 }
  2329.             }
  2330.         } // End of Non Uniform
  2331.  
  2332.         public static void Sobel(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy)
  2333.         {
  2334.             unsafe
  2335.             {
  2336.                 // direct access to the image memory(sequencial)
  2337.                 // direcion top left -> bottom right
  2338.                 MIplImage m = img.MIplImage;
  2339.                 MIplImage m1 = imgCopy.MIplImage;
  2340.                 byte* dataPtr = (byte*)m.imageData.ToPointer(); // Pointer to the image
  2341.                 byte* auxdataPtr = (byte*)m1.imageData.ToPointer(); // Pointer to the image
  2342.                 byte* dataPtrStatic = dataPtr; // Pointer de referência para o início da imagem a editar
  2343.                 byte* a, b, c, d, e, f, g, h, i;
  2344.  
  2345.                 int width = img.Width;
  2346.                 int height = img.Height;
  2347.                 int nChan = m.nChannels; // number of channels - 3
  2348.                 int padding = m.widthStep - m.nChannels * m.width; // alinhament bytes (padding)
  2349.                 int x, y;
  2350.  
  2351.                 if (nChan == 3)
  2352.                 {
  2353.                     for (y = 0; y < height; y++)  //processar apenas a imagem interior sem as bordas
  2354.                     {
  2355.                         for (x = 0; x < width; x++)
  2356.                         {
  2357.                             int Sb = 0;
  2358.                             int Sg = 0;
  2359.                             int Sr = 0;
  2360.  
  2361.                             dataPtr = (dataPtrStatic + y * m.widthStep + x * nChan);
  2362.  
  2363.                             a = (auxdataPtr + (y - 1) * m.widthStep + (x - 1) * nChan);
  2364.                             b = (auxdataPtr + (y - 1) * m.widthStep + x * nChan);
  2365.                             c = (auxdataPtr + (y - 1) * m.widthStep + (x + 1) * nChan);
  2366.                             d = (auxdataPtr + y * m.widthStep + (x - 1) * nChan);
  2367.                             e = (auxdataPtr + y * m.widthStep + x * nChan);
  2368.                             f = (auxdataPtr + y * m.widthStep + (x + 1) * nChan);
  2369.                             g = (auxdataPtr + (y + 1) * m.widthStep + (x - 1) * nChan);
  2370.                             h = (auxdataPtr + (y + 1) * m.widthStep + x * nChan);
  2371.                             i = (auxdataPtr + (y + 1) * m.widthStep + (x + 1) * nChan);
  2372.  
  2373.                             // dentro da imagem
  2374.                             if ((y > 0 && y < height - 1) && (x > 0 && x < width - 1))
  2375.                             {
  2376.                                 Sb = Math.Abs(a[0] + 2 * d[0] + g[0] - c[0] - 2 * f[0] - i[0]) + Math.Abs(g[0] + 2 * h[0] + i[0] - a[0] - 2 * b[0] - c[0]);
  2377.                                 Sg = Math.Abs(a[1] + 2 * d[1] + g[1] - c[1] - 2 * f[1] - i[1]) + Math.Abs(g[1] + 2 * h[1] + i[1] - a[1] - 2 * b[1] - c[1]);
  2378.                                 Sr = Math.Abs(a[2] + 2 * d[2] + g[2] - c[2] - 2 * f[2] - i[2]) + Math.Abs(g[2] + 2 * h[2] + i[2] - a[2] - 2 * b[2] - c[2]);
  2379.                             }
  2380.                             // última coluna \ cantos
  2381.                             if ((x == width - 1) && (y > 0 && y < height - 1))
  2382.                             {
  2383.                                 Sb = Math.Abs(a[0] + 2 * d[0] + g[0] - b[0] - 2 * e[0] - h[0]) + Math.Abs(g[0] + 3 * h[0] - a[0] - 3 * b[0]);
  2384.                                 Sg = Math.Abs(a[1] + 2 * d[1] + g[1] - b[1] - 2 * e[1] - h[1]) + Math.Abs(g[1] + 3 * h[1] - a[1] - 3 * b[1]);
  2385.                                 Sr = Math.Abs(a[2] + 2 * d[2] + g[2] - b[2] - 2 * e[2] - h[2]) + Math.Abs(g[2] + 3 * h[2] - a[2] - 3 * b[2]);
  2386.                             }
  2387.                             // última linha \ cantos
  2388.                             if ((x > 0 && x < width - 1) && (y == height - 1))
  2389.                             {
  2390.                                 Sb = Math.Abs(a[0] + 3 * d[0] - c[0] - 3 * f[0]) + Math.Abs(d[0] + 2 * e[0] + f[0] - a[0] - 2 * b[0] - c[0]);
  2391.                                 Sg = Math.Abs(a[1] + 3 * d[1] - c[1] - 3 * f[1]) + Math.Abs(d[1] + 2 * e[1] + f[1] - a[1] - 2 * b[1] - c[1]);
  2392.                                 Sr = Math.Abs(a[2] + 3 * d[2] - c[2] - 3 * f[2]) + Math.Abs(d[2] + 2 * e[2] + f[2] - a[2] - 2 * b[2] - c[2]);
  2393.                             }
  2394.                             // primeira coluna \ cantos
  2395.                             if ((x == 0) && (y > 0 && y < height - 1))
  2396.                             {
  2397.                                 Sb = Math.Abs(b[0] + 2 * e[0] + h[0] - c[0] - 2 * f[0] - i[0]) + Math.Abs(3 * h[0] + i[0] - 3 * b[0] - c[0]);
  2398.                                 Sg = Math.Abs(b[1] + 2 * e[1] + h[1] - c[1] - 2 * f[1] - i[1]) + Math.Abs(3 * h[1] + i[1] - 3 * b[1] - c[1]);
  2399.                                 Sr = Math.Abs(b[2] + 2 * e[2] + h[2] - c[2] - 2 * f[2] - i[2]) + Math.Abs(3 * h[2] + i[2] - 3 * b[2] - c[2]);
  2400.                             }
  2401.                             // primeira linha \ cantos
  2402.                             if ((x > 0 && x < width - 1) && (y == 0))
  2403.                             {
  2404.                                 Sb = Math.Abs(3 * d[0] + g[0] - 3 * f[0] - i[0]) + Math.Abs(g[0] + 2 * h[0] + i[0] - d[0] - 2 * e[0] - f[0]);
  2405.                                 Sg = Math.Abs(3 * d[1] + g[1] - 3 * f[1] - i[1]) + Math.Abs(g[1] + 2 * h[1] + i[1] - d[1] - 2 * e[1] - f[1]);
  2406.                                 Sr = Math.Abs(3 * d[2] + g[2] - 3 * f[2] - i[2]) + Math.Abs(g[2] + 2 * h[2] + i[2] - d[2] - 2 * e[2] - f[2]);
  2407.                             }
  2408.                             // canto sup esq
  2409.                             if ((x == 0) && (y == 0))
  2410.                             {
  2411.                                 Sb = Math.Abs(3 * e[0] + h[0] - 3 * f[0] - i[0]) + Math.Abs(3 * h[0] + i[0] - 3 * e[0] - f[0]);
  2412.                                 Sg = Math.Abs(3 * e[1] + h[1] - 3 * f[1] - i[1]) + Math.Abs(3 * h[1] + i[1] - 3 * e[1] - f[1]);
  2413.                                 Sr = Math.Abs(3 * e[2] + h[2] - 3 * f[2] - i[2]) + Math.Abs(3 * h[2] + i[2] - 3 * e[2] - f[2]);
  2414.                             }
  2415.                             // canto sup dir
  2416.                             if ((x == width - 1) && (y == 0))
  2417.                             {
  2418.                                 Sb = Math.Abs(3 * d[0] + g[0] - 3 * e[0] - h[0]) + Math.Abs(g[0] + 3 * h[0] - d[0] - 3 * e[0]);
  2419.                                 Sg = Math.Abs(3 * d[1] + g[1] - 3 * e[1] - h[1]) + Math.Abs(g[1] + 3 * h[1] - d[1] - 3 * e[1]);
  2420.                                 Sr = Math.Abs(3 * d[2] + g[2] - 3 * e[2] - h[2]) + Math.Abs(g[2] + 3 * h[2] - d[2] - 3 * e[2]);
  2421.                             }
  2422.                             // canto inf esq
  2423.                             if ((x == 0) && (y == height - 1))
  2424.                             {
  2425.                                 Sb = Math.Abs(b[0] + 3 * e[0] - c[0] - 3 * f[0]) + Math.Abs(3 * e[0] + f[0] - 3 * b[0] - c[0]);
  2426.                                 Sg = Math.Abs(b[1] + 3 * e[1] - c[1] - 3 * f[1]) + Math.Abs(3 * e[1] + f[1] - 3 * b[1] - c[1]);
  2427.                                 Sr = Math.Abs(b[2] + 3 * e[2] - c[2] - 3 * f[2]) + Math.Abs(3 * e[2] + f[2] - 3 * b[2] - c[2]);
  2428.                             }
  2429.                             // canto inf dir
  2430.                             if ((x == width - 1) && (y == height - 1))
  2431.                             {
  2432.                                 Sb = Math.Abs(a[0] + 3 * d[0] - b[0] - 3 * e[0]) + Math.Abs(d[0] + 3 * e[0] - a[0] - 3 * b[0]);
  2433.                                 Sg = Math.Abs(a[1] + 3 * d[1] - b[1] - 3 * e[1]) + Math.Abs(d[1] + 3 * e[1] - a[1] - 3 * b[1]);
  2434.                                 Sr = Math.Abs(a[2] + 3 * d[2] - b[2] - 3 * e[2]) + Math.Abs(d[2] + 3 * e[2] - a[2] - 3 * b[2]);
  2435.                             }
  2436.  
  2437.                             if (Sb > 255) Sb = 255;
  2438.                             else if (Sb < 0) Sb = 0;
  2439.  
  2440.                             if (Sg > 255) Sg = 255;
  2441.                             else if (Sg < 0) Sg = 0;
  2442.  
  2443.                             if (Sr > 255) Sr = 255;
  2444.                             else if (Sr < 0) Sr = 0;
  2445.  
  2446.                             dataPtr[0] = (byte)Sb;
  2447.                             dataPtr[1] = (byte)Sg;
  2448.                             dataPtr[2] = (byte)Sr;
  2449.                         }
  2450.                     }
  2451.                 }
  2452.             }
  2453.         } // End of Sobel
  2454.  
  2455.         public static void Diferentiation(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy)
  2456.         {
  2457.             unsafe
  2458.             {
  2459.                 MIplImage m = imgCopy.MIplImage;
  2460.                 MIplImage d = img.MIplImage;
  2461.                 byte* dataPtr_org = (byte*)m.imageData.ToPointer(); // Pointer to the original image
  2462.                 byte* dataPtr = (byte*)d.imageData.ToPointer();   // Pointer to the final image
  2463.                 byte* centerPx, o_centerPx;
  2464.  
  2465.                 int w = img.Width;
  2466.                 int h = img.Height;
  2467.                 int nChan = m.nChannels; // number of channels - 3
  2468.                 int widthStep = m.widthStep;
  2469.                 int x, y;
  2470.                 double[] result = new double[3];
  2471.  
  2472.                 if (nChan == 3) // image in RGB
  2473.                 {
  2474.                     // Left Border
  2475.                     x = w - 1;
  2476.                     for (y = 0; y < h - 1; y++)
  2477.                     {
  2478.                         o_centerPx = dataPtr_org + y * widthStep + x * nChan;
  2479.                         centerPx = dataPtr + y * widthStep + x * nChan;
  2480.  
  2481.                         result[0] = (Math.Abs((int)(o_centerPx)[0] - (o_centerPx)[0]) + Math.Abs((int)(o_centerPx)[0] - (o_centerPx + widthStep)[0]));
  2482.                         result[1] = (Math.Abs((int)(o_centerPx)[1] - (o_centerPx)[1]) + Math.Abs((int)(o_centerPx)[1] - (o_centerPx + widthStep)[1]));
  2483.                         result[2] = (Math.Abs((int)(o_centerPx)[2] - (o_centerPx)[2]) + Math.Abs((int)(o_centerPx)[2] - (o_centerPx + widthStep)[2]));
  2484.  
  2485.                         centerPx[0] = (byte)(result[0] > 255 ? 255 : Math.Round(result[0]));
  2486.                         centerPx[1] = (byte)(result[1] > 255 ? 255 : Math.Round(result[1]));
  2487.                         centerPx[2] = (byte)(result[2] > 255 ? 255 : Math.Round(result[2]));
  2488.                     }
  2489.  
  2490.                     // Bottom Border
  2491.                     y = h - 1;
  2492.                     for (x = 0; x < w - 1; x++)
  2493.                     {
  2494.                         o_centerPx = dataPtr_org + y * widthStep + x * nChan;
  2495.                         centerPx = dataPtr + y * widthStep + x * nChan;
  2496.  
  2497.                         result[0] = (Math.Abs((int)(o_centerPx)[0] - (o_centerPx + nChan)[0]) + Math.Abs((int)(o_centerPx)[0] - (o_centerPx)[0]));
  2498.                         result[1] = (Math.Abs((int)(o_centerPx)[1] - (o_centerPx + nChan)[1]) + Math.Abs((int)(o_centerPx)[1] - (o_centerPx)[1]));
  2499.                         result[2] = (Math.Abs((int)(o_centerPx)[2] - (o_centerPx + nChan)[2]) + Math.Abs((int)(o_centerPx)[2] - (o_centerPx)[2]));
  2500.  
  2501.                         centerPx[0] = (byte)(result[0] > 255 ? 255 : Math.Round(result[0]));
  2502.                         centerPx[1] = (byte)(result[1] > 255 ? 255 : Math.Round(result[1]));
  2503.                         centerPx[2] = (byte)(result[2] > 255 ? 255 : Math.Round(result[2]));
  2504.                     }
  2505.  
  2506.                     // Bottom Right Corner
  2507.                     o_centerPx = dataPtr_org + y * widthStep + x * nChan;
  2508.                     centerPx = dataPtr + y * widthStep + x * nChan;
  2509.  
  2510.                     x = w - 1; y = h - 1;
  2511.  
  2512.                     centerPx[0] = (byte)0;
  2513.                     centerPx[1] = (byte)0;
  2514.                     centerPx[2] = (byte)0;
  2515.  
  2516.                     // *** CORE ***
  2517.                     for (y = 0; y < h - 1; y++)
  2518.                     {
  2519.                         for (x = 0; x < w - 1; x++)
  2520.                         {
  2521.                             o_centerPx = dataPtr_org + y * widthStep + x * nChan;
  2522.                             centerPx = dataPtr + y * widthStep + x * nChan;
  2523.  
  2524.                             result[0] = (Math.Abs((int)(o_centerPx)[0] - (o_centerPx + nChan)[0]) + Math.Abs((int)(o_centerPx)[0] - (o_centerPx + widthStep)[0]));
  2525.                             result[1] = (Math.Abs((int)(o_centerPx)[1] - (o_centerPx + nChan)[1]) + Math.Abs((int)(o_centerPx)[1] - (o_centerPx + widthStep)[1]));
  2526.                             result[2] = (Math.Abs((int)(o_centerPx)[2] - (o_centerPx + nChan)[2]) + Math.Abs((int)(o_centerPx)[2] - (o_centerPx + widthStep)[2]));
  2527.  
  2528.                             centerPx[0] = (byte)(result[0] > 255 ? 255 : Math.Round(result[0]));
  2529.                             centerPx[1] = (byte)(result[1] > 255 ? 255 : Math.Round(result[1]));
  2530.                             centerPx[2] = (byte)(result[2] > 255 ? 255 : Math.Round(result[2]));
  2531.                         }
  2532.                     }
  2533.                 } // End of nChan = 3
  2534.             } // End of Unsafe
  2535.         } // End of Diferentiation
  2536.  
  2537.         public static void Median(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy)
  2538.         {
  2539.             unsafe
  2540.             {
  2541.                 MIplImage m = imgCopy.MIplImage;
  2542.                 MIplImage d = img.MIplImage;
  2543.  
  2544.                 img.SmoothMedian(3).CopyTo(img);
  2545.             } // End of Unsafe
  2546.         } // End of Median
  2547.  
  2548.         public static int[] Histogram_Gray(Emgu.CV.Image<Bgr, byte> img)
  2549.         {
  2550.             unsafe
  2551.             {
  2552.                 MIplImage d = img.MIplImage;
  2553.                 byte* dataPtr = (byte*)d.imageData.ToPointer();   // Pointer to the final image
  2554.  
  2555.                 int w = img.Width;
  2556.                 int h = img.Height;
  2557.                 int nChan = d.nChannels; // number of channels - 3
  2558.                 int widthStep = d.widthStep;
  2559.                 int padding = widthStep - nChan * w;
  2560.                 int x, y;
  2561.  
  2562.                 byte gray;
  2563.                 int[] result = new int[256];
  2564.  
  2565.                 if (nChan == 1)
  2566.                 {
  2567.                     for (y = 0; y < h; y++)
  2568.                     {
  2569.                         for (x = 0; x < w; x++)
  2570.                         {
  2571.                             result[dataPtr[0]]++;
  2572.                             dataPtr += nChan;
  2573.                         }
  2574.                         dataPtr += padding;
  2575.                     }
  2576.                 } // End of nChan = 1
  2577.  
  2578.                 else if (nChan == 3)
  2579.                 {
  2580.                     for (y = 0; y < h; y++)
  2581.                     {
  2582.                         for (x = 0; x < w; x++)
  2583.                         {
  2584.                             gray = (byte)Math.Round((dataPtr[0] + dataPtr[1] + dataPtr[2]) / 3.0);
  2585.  
  2586.                             result[dataPtr[gray]]++;
  2587.                             dataPtr += nChan;
  2588.                         }
  2589.                         dataPtr += padding;
  2590.                     }
  2591.                 } // End of nChan = 3
  2592.  
  2593.                 return result;
  2594.             } // End of Unsafe
  2595.         } // End of Histogram_Gray
  2596.  
  2597.         public static int[,] Histogram_RGB(Emgu.CV.Image<Bgr, byte> img)
  2598.         {
  2599.             unsafe
  2600.             {
  2601.                 MIplImage d = img.MIplImage;
  2602.                 byte* dataPtr = (byte*)d.imageData.ToPointer();   // Pointer to the final image
  2603.  
  2604.                 int w = img.Width;
  2605.                 int h = img.Height;
  2606.                 int nChan = d.nChannels; // number of channels - 3
  2607.                 int widthStep = d.widthStep;
  2608.                 int padding = widthStep - nChan * w;
  2609.                 int x, y;
  2610.                 int[,] result = new int[3, 256];
  2611.  
  2612.                 if (nChan == 3) // image in RGB
  2613.                 {
  2614.                     // *** CORE ***
  2615.                     for (y = 0; y < h; y++)
  2616.                     {
  2617.                         for (x = 0; x < w; x++)
  2618.                         {
  2619.                             result[0, dataPtr[0]]++;
  2620.                             result[1, dataPtr[1]]++;
  2621.                             result[2, dataPtr[2]]++;
  2622.                             dataPtr += nChan;
  2623.                         }
  2624.                         dataPtr += padding;
  2625.                     }
  2626.                 } // End of nChan = 3
  2627.                 return result;
  2628.             } // End of Unsafe
  2629.         } // End of Histogram_RGB
  2630.  
  2631.         public static int[,] Histogram_All(Emgu.CV.Image<Bgr, byte> img)
  2632.         {
  2633.             unsafe
  2634.             {
  2635.                 MIplImage d = img.MIplImage;
  2636.                 byte* dataPtr = (byte*)d.imageData.ToPointer();   // Pointer to the final image
  2637.  
  2638.                 int w = img.Width;
  2639.                 int h = img.Height;
  2640.                 int nChan = d.nChannels; // number of channels - 3
  2641.                 int widthStep = d.widthStep;
  2642.                 int padding = widthStep - nChan * w;
  2643.                 int x, y;
  2644.                 byte gray;
  2645.                 int[,] result = new int[4, 256];
  2646.  
  2647.                 if (nChan == 3) // image in RGB
  2648.                 {
  2649.                     // *** CORE ***
  2650.                     for (y = 0; y < h; y++)
  2651.                     {
  2652.                         for (x = 0; x < w; x++)
  2653.                         {
  2654.                             gray = (byte)Math.Round((dataPtr[0] + dataPtr[1] + dataPtr[2]) / 3.0);
  2655.  
  2656.                             result[0, dataPtr[0]]++; //R
  2657.                             result[1, dataPtr[1]]++; //G
  2658.                             result[2, dataPtr[2]]++; //B
  2659.                             result[3, dataPtr[gray]]++; //B
  2660.  
  2661.                             dataPtr += nChan;
  2662.                         }
  2663.                         dataPtr += padding;
  2664.                     }
  2665.                 } // End of nChan = 3
  2666.                 return result;
  2667.             } // End of Unsafe
  2668.         } // End of Histogram_All  
  2669.  
  2670.         public static void ConvertToBW(Emgu.CV.Image<Bgr, byte> img, int threshold)
  2671.         {
  2672.             unsafe
  2673.             {
  2674.                 // direct access to the image memory(sequencial)
  2675.                 // direcion top left -> bottom right
  2676.  
  2677.                 MIplImage m = img.MIplImage;
  2678.                 byte* dataPtr = (byte*)m.imageData.ToPointer(); // Pointer to the image
  2679.  
  2680.                 int width = img.Width;
  2681.                 int height = img.Height;
  2682.                 int nChan = m.nChannels; // number of channels - 3
  2683.                 int padding = m.widthStep - m.nChannels * m.width; // alinhament bytes (padding)
  2684.  
  2685.                 if (nChan == 3) // image in RGB
  2686.                 {
  2687.                     for (int y = 0; y < height; y++)
  2688.                     {
  2689.                         for (int x = 0; x < width; x++)
  2690.                         {
  2691.                             if (Math.Round(((float)dataPtr[0] + (float)dataPtr[1] + (float)dataPtr[2]) / 3) <= threshold)
  2692.                             {
  2693.                                 dataPtr[0] = 0;
  2694.                                 dataPtr[1] = 0;
  2695.                                 dataPtr[2] = 0;
  2696.                             }
  2697.                             else
  2698.                             {
  2699.                                 dataPtr[0] = 255;
  2700.                                 dataPtr[1] = 255;
  2701.                                 dataPtr[2] = 255;
  2702.                             }
  2703.  
  2704.                             // advance the pointer to the next pixel
  2705.                             dataPtr += nChan;
  2706.                         }
  2707.  
  2708.                         //at the end of the line advance the pointer by the aligment bytes (padding)
  2709.                         dataPtr += padding;
  2710.                     }
  2711.                 }
  2712.             }
  2713.         } // End of ConvertToBW
  2714.  
  2715.         public static void ConvertToBW_Otsu(Emgu.CV.Image<Bgr, byte> img)
  2716.         {
  2717.             unsafe
  2718.             {
  2719.                 // direct access to the image memory(sequencial)
  2720.                 // direcion top left -> bottom right
  2721.  
  2722.                 MIplImage m = img.MIplImage;
  2723.                 byte* dataPtr = (byte*)m.imageData.ToPointer(); // Pointer to the image
  2724.                 byte blue, green, red;
  2725.  
  2726.                 int width = img.Width;
  2727.                 int height = img.Height;
  2728.                 int nChan = m.nChannels; // number of channels - 3
  2729.                 int padding = m.widthStep - m.nChannels * m.width; // alinhament bytes (padding)
  2730.  
  2731.                 int gray;
  2732.                 int nPixels = width * height;
  2733.                 int t, threshold = 0;
  2734.  
  2735.                 float[] pixels = new float[256];
  2736.                 float[] probPixel = new float[256];
  2737.  
  2738.                 float q1, q2;
  2739.                 float u1, u2;
  2740.                 float varInterClass = 0;
  2741.                 float varInterClassAux;
  2742.  
  2743.                 if (nChan == 3) // image in RGB
  2744.                 {
  2745.                     for (int y = 0; y < height; y++)
  2746.                     {
  2747.                         for (int x = 0; x < width; x++)
  2748.                         {
  2749.                             blue = dataPtr[0];
  2750.                             green = dataPtr[1];
  2751.                             red = dataPtr[2];
  2752.  
  2753.                             // convert to gray
  2754.                             gray = (int)Math.Round(((float)(blue + green + red) / 3));
  2755.  
  2756.                             pixels[gray] += 1;
  2757.  
  2758.                             // advance the pointer to the next pixel
  2759.                             dataPtr += nChan;
  2760.                         }
  2761.                     }
  2762.  
  2763.                     for (int i = 0; i < 256; i++)
  2764.                     {
  2765.                         probPixel[i] = pixels[i] / nPixels;
  2766.                     }
  2767.  
  2768.                     for (t = 0; t < 256; t++)
  2769.                     {
  2770.                         q1 = 0; q2 = 0;
  2771.                         u1 = 0; u2 = 0;
  2772.                         varInterClassAux = 0;
  2773.  
  2774.                         for (int i = 0; i <= t; i++)
  2775.                         {
  2776.                             q1 += probPixel[i];
  2777.                         }
  2778.                         for (int i = 0; i <= t; i++)
  2779.                         {
  2780.                             u1 += i * probPixel[i];
  2781.                         }
  2782.  
  2783.                         u1 = u1 / q1;
  2784.  
  2785.                         for (int j = t + 1; j < 256; j++)
  2786.                         {
  2787.                             q2 += probPixel[j];
  2788.                         }
  2789.                         for (int j = t + 1; j < 256; j++)
  2790.                         {
  2791.                             u2 += j * probPixel[j];
  2792.                         }
  2793.  
  2794.                         u2 = u2 / q2;
  2795.  
  2796.                         varInterClassAux = q1 * q2 * (u1 - u2) * (u1 - u2);
  2797.  
  2798.                         if (varInterClassAux >= varInterClass)
  2799.                         {
  2800.                             varInterClass = varInterClassAux;
  2801.                             threshold = t;
  2802.                         }
  2803.                     }
  2804.  
  2805.                     ConvertToBW(img, threshold);
  2806.                 }
  2807.             }
  2808.         } // End of ConvertToBW_Otsu
  2809.  
  2810.  
  2811.         // ***  Aux Puzzle Functions ***
  2812.  
  2813.         public static void Translation_xy(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy, double[] posic_inicial, double[] posic_final, byte[] bckgrd)
  2814.         {
  2815.             unsafe
  2816.             {
  2817.                 MIplImage m = img.MIplImage;
  2818.                 MIplImage c = imgCopy.MIplImage;
  2819.                 byte* dataPtr = (byte*)m.imageData.ToPointer(); // Pointer to the image
  2820.                 byte* dataPtrCopy = (byte*)c.imageData.ToPointer(); // Pointer to the image
  2821.  
  2822.                 int width = img.Width;
  2823.                 int height = img.Height;
  2824.                 int nChan = m.nChannels; // number of channels - 3
  2825.                 int widthStep = m.widthStep;
  2826.                 int padding = widthStep - m.nChannels * m.width; // alinhament bytes (padding)
  2827.                 byte blue, green, red;
  2828.                 int x, y;
  2829.                 int dx, dy;
  2830.  
  2831.                 dx = (int)(posic_final[0] - posic_inicial[0]);
  2832.                 dy = (int)(posic_final[1] - posic_inicial[1]);
  2833.  
  2834.                 if (nChan == 3)
  2835.                 {
  2836.                     for (y = (int)posic_inicial[1]; y <= posic_inicial[3]; y++)
  2837.                     {
  2838.                         for (x = (int)posic_inicial[0]; x <= posic_inicial[2]; x++)
  2839.                         {
  2840.                             blue = (byte)(dataPtrCopy + y * widthStep + x * nChan)[0];
  2841.                             green = (byte)(dataPtrCopy + y * widthStep + x * nChan)[1];
  2842.                             red = (byte)(dataPtrCopy + y * widthStep + x * nChan)[2];
  2843.  
  2844.  
  2845.                             // Fill with background where the piece used to be
  2846.                             if (dx < 0 && dy < 0)
  2847.                             {
  2848.                                 if (y >= posic_inicial[1] + dy || x >= posic_inicial[0] + dy)
  2849.                                 {
  2850.                                     // = background colour
  2851.                                     (dataPtrCopy + y * widthStep + x * nChan)[0] = bckgrd[0];
  2852.                                     (dataPtrCopy + y * widthStep + x * nChan)[1] = bckgrd[1];
  2853.                                     (dataPtrCopy + y * widthStep + x * nChan)[2] = bckgrd[2];
  2854.                                 }
  2855.                             }
  2856.                             else if (dx < 0 && dy >= 0)
  2857.                             {
  2858.                                 if (y < posic_inicial[1] + dy || x >= posic_inicial[2] + dx)
  2859.                                 {
  2860.                                     // = background colour
  2861.                                     (dataPtrCopy + y * widthStep + x * nChan)[0] = bckgrd[0];
  2862.                                     (dataPtrCopy + y * widthStep + x * nChan)[1] = bckgrd[1];
  2863.                                     (dataPtrCopy + y * widthStep + x * nChan)[2] = bckgrd[2];
  2864.                                 }
  2865.                             }
  2866.                             else if (dx >= 0 && dy < 0)
  2867.                             {
  2868.                                 if (y >= posic_inicial[3] + dy || x < posic_inicial[0] + dx)
  2869.                                 {
  2870.                                     // = background colour
  2871.                                     (dataPtrCopy + y * widthStep + x * nChan)[0] = bckgrd[0];
  2872.                                     (dataPtrCopy + y * widthStep + x * nChan)[1] = bckgrd[1];
  2873.                                     (dataPtrCopy + y * widthStep + x * nChan)[2] = bckgrd[2];
  2874.                                 }
  2875.                             }
  2876.                             else if (dx >= 0 && dy >= 0)
  2877.                             {
  2878.                                 if (y < posic_inicial[1] + dy || x < posic_inicial[0] + dx)
  2879.                                 {
  2880.                                     // = background colour
  2881.                                     (dataPtrCopy + y * widthStep + x * nChan)[0] = bckgrd[0];
  2882.                                     (dataPtrCopy + y * widthStep + x * nChan)[1] = bckgrd[1];
  2883.                                     (dataPtrCopy + y * widthStep + x * nChan)[2] = bckgrd[2];
  2884.                                 }
  2885.                             }
  2886.  
  2887.                             if (x + dx >= 0 && y + dy >= 0 && x + dx < width && y + dy < height)
  2888.                             {
  2889.                                 (dataPtr + (y + dy) * widthStep + (x + dx) * nChan)[0] = blue;
  2890.                                 (dataPtr + (y + dy) * widthStep + (x + dx) * nChan)[1] = green;
  2891.                                 (dataPtr + (y + dy) * widthStep + (x + dx) * nChan)[2] = red;
  2892.                             }
  2893.                         }
  2894.                     }
  2895.                 }
  2896.             }
  2897.         } // End of Translation XY
  2898.  
  2899.         public static void Translation__xy_NoReplace(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy, double[] posic_inicial, double[] posic_final)
  2900.         {
  2901.             unsafe
  2902.             {
  2903.                 MIplImage m = img.MIplImage;
  2904.                 MIplImage c = imgCopy.MIplImage;
  2905.                 byte* dataPtr = (byte*)m.imageData.ToPointer(); // Pointer to the image
  2906.                 byte* dataPtrCopy = (byte*)c.imageData.ToPointer(); // Pointer to the image
  2907.  
  2908.                 int width = img.Width;
  2909.                 int height = img.Height;
  2910.                 int nChan = m.nChannels; // number of channels - 3
  2911.                 int widthStep = m.widthStep;
  2912.                 int padding = widthStep - m.nChannels * m.width; // alinhament bytes (padding)
  2913.                 byte blue, green, red;
  2914.                 int x, y;
  2915.                 int dx, dy;
  2916.  
  2917.                 dx = (int)(posic_final[0] - posic_inicial[0]);
  2918.                 dy = (int)(posic_final[1] - posic_inicial[1]);
  2919.  
  2920.                 if (nChan == 3)
  2921.                 {
  2922.                     for (y = (int)posic_inicial[1]; y <= posic_inicial[3]; y++)
  2923.                     {
  2924.                         for (x = (int)posic_inicial[0]; x <= posic_inicial[2]; x++)
  2925.                         {
  2926.                             blue = (byte)(dataPtrCopy + y * widthStep + x * nChan)[0];
  2927.                             green = (byte)(dataPtrCopy + y * widthStep + x * nChan)[1];
  2928.                             red = (byte)(dataPtrCopy + y * widthStep + x * nChan)[2];
  2929.  
  2930.  
  2931.                             if (x + dx >= 0
  2932.                                 && y + dy >= 0
  2933.                                 && x + dx < width
  2934.                                 && y + dy < height)
  2935.                             {
  2936.                                 (dataPtr + (y + dy) * widthStep + (x + dx) * nChan)[0] = blue;
  2937.                                 (dataPtr + (y + dy) * widthStep + (x + dx) * nChan)[1] = green;
  2938.                                 (dataPtr + (y + dy) * widthStep + (x + dx) * nChan)[2] = red;
  2939.                             }
  2940.                         }
  2941.                     }
  2942.                 }
  2943.             }
  2944.         } // End of Translation XY No Replace
  2945.  
  2946.         static public void RotatePieces(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy, int[,] labels, Dictionary<int, double[]> obj_list)
  2947.         {
  2948.             unsafe
  2949.             {
  2950.                 MIplImage m = img.MIplImage;
  2951.                 MIplImage mc = imgCopy.MIplImage;
  2952.  
  2953.                 byte* dataPtr = (byte*)m.imageData.ToPointer(); // Pointer to the image
  2954.                 byte* auxdataPtr = (byte*)mc.imageData.ToPointer(); // Pointer to the image
  2955.  
  2956.                 byte* px;
  2957.                 byte* pxCopy;
  2958.                 byte* a, b, c, d;
  2959.  
  2960.                 int x, y;
  2961.                 int widthStep = m.widthStep;
  2962.                 int nChan = m.nChannels; // number of channels - 3
  2963.  
  2964.                 double[] sqr;
  2965.  
  2966.                 Dictionary<int, double[]>.Enumerator objlist_enum = obj_list.GetEnumerator();
  2967.  
  2968.                 while (objlist_enum.MoveNext())
  2969.                 {
  2970.                     sqr = objlist_enum.Current.Value;
  2971.  
  2972.                     if (sqr[4] != 0)
  2973.                     {
  2974.                         // Must rotate image
  2975.                         sqr[4] = (Math.PI * (int)sqr[4]) / 180;
  2976.                         double sin = Math.Sin(sqr[4]);
  2977.                         double cos = Math.Cos(sqr[4]);
  2978.                         double w = sqr[2] + sqr[0] + 1;
  2979.                         double h = sqr[3] + sqr[1] + 1;
  2980.  
  2981.                         double xc = (-((w) / 2) * cos) - ((h / 2) * sin) + (w / 2);
  2982.                         double yc = ((w / 2) * sin) - ((h / 2) * cos) + (h / 2);
  2983.  
  2984.                         double xo, yo;
  2985.                         double j, k;
  2986.                         int xr, yr;
  2987.  
  2988.                         double blueS, greenS, redS;
  2989.                         double blueI, greenI, redI;
  2990.  
  2991.                         // Get new corners for rotated piece
  2992.                         double[] corners = new double[4] { sqr[0], sqr[1], sqr[2], sqr[3] };
  2993.  
  2994.                         for (y = (int)sqr[1]; y <= sqr[3]; y++)
  2995.                         {
  2996.                             for (x = (int)sqr[0]; x <= sqr[2]; x++)
  2997.                             {
  2998.                                 // Reset the label values
  2999.                                 labels[y, x] = int.MaxValue;
  3000.  
  3001.                                 xo = xc + x * cos + y * sin;
  3002.                                 yo = yc - x * sin + y * cos;
  3003.  
  3004.                                 j = xo % 1;
  3005.                                 k = yo % 1;
  3006.  
  3007.                                 xr = (int)(xo - j);
  3008.                                 yr = (int)(yo - k);
  3009.  
  3010.  
  3011.                                 px = (dataPtr + y * m.widthStep + x * nChan);
  3012.                                 pxCopy = (auxdataPtr + yr * widthStep + xr * nChan);
  3013.  
  3014.                                 if (xr < sqr[0] - 1 || xr > sqr[2] || yr < sqr[1] - 1 || yr > sqr[3])
  3015.                                 {
  3016.                                     px[0] = dataPtr[0];
  3017.                                     px[1] = dataPtr[1];
  3018.                                     px[2] = dataPtr[2];
  3019.                                 }
  3020.                                 else if ((xr >= 0 && xr < w) && (yr >= 0 && yr < h))
  3021.                                 {
  3022.                                     // Update the new coordinates with the same label
  3023.                                     labels[y, x] = objlist_enum.Current.Key;
  3024.  
  3025.                                     a = (pxCopy);
  3026.                                     b = (pxCopy + nChan);
  3027.                                     c = (pxCopy + widthStep);
  3028.                                     d = (pxCopy + nChan + widthStep);
  3029.  
  3030.                                     // Bx+j,y = (1 - j) * Bx,y + j * Bx+1,y
  3031.                                     blueS = (1 - j) * a[0] + j * b[0];
  3032.                                     greenS = (1 - j) * a[1] + j * b[1];
  3033.                                     redS = (1 - j) * a[2] + j * b[2];
  3034.  
  3035.                                     // Bx+j,y+1 = (1 - j) * Bx,y+1 + j * Bx+1,y+1
  3036.                                     blueI = (1 - j) * c[0] + j * d[0];
  3037.                                     greenI = (1 - j) * c[1] + j * d[1];
  3038.                                     redI = (1 - j) * c[2] + j * d[2];
  3039.  
  3040.                                     // Bx+j,y+k = (1 - k) * Bx+j,y + k * Bx+j,y+1
  3041.                                     px[0] = (byte)(Math.Round((1 - k) * blueS + k * blueI));
  3042.                                     px[1] = (byte)(Math.Round((1 - k) * greenS + k * greenI));
  3043.                                     px[2] = (byte)(Math.Round((1 - k) * redS + k * redI));
  3044.                                 }
  3045.                                 else
  3046.                                 {
  3047.                                     px[0] = 0;
  3048.                                     px[1] = 0;
  3049.                                     px[2] = 0;
  3050.                                 }
  3051.                             } // End of For X
  3052.                         } // End of For Y
  3053.  
  3054.                         // Reattribute labels and define new corner values
  3055.                         bool FIRST_OCCURENCE = false;
  3056.  
  3057.                         for (y = (int)sqr[1]; y <= sqr[3]; y++)
  3058.                         {
  3059.                             for (x = (int)sqr[0]; x <= sqr[2]; x++)
  3060.                             {
  3061.                                 px = (dataPtr + y * m.widthStep + x * nChan);
  3062.                                 if (px[0] != dataPtr[0] && px[1] != dataPtr[1] && px[2] != dataPtr[2])
  3063.                                 {
  3064.                                     labels[y, x] = objlist_enum.Current.Key;
  3065.  
  3066.                                     if (!FIRST_OCCURENCE)
  3067.                                     {
  3068.                                         FIRST_OCCURENCE = true;
  3069.                                         corners[0] = x;
  3070.                                         corners[1] = y;
  3071.                                         corners[2] = x;
  3072.                                         corners[3] = y;
  3073.                                     }
  3074.                                     else
  3075.                                     {
  3076.                                         if (x < corners[0])
  3077.                                             corners[0] = x;
  3078.  
  3079.                                         if (y < corners[1])
  3080.                                             corners[1] = y;
  3081.  
  3082.                                         if (x > corners[2])
  3083.                                             corners[2] = x;
  3084.  
  3085.                                         if (y > corners[3])
  3086.                                             corners[3] = y;
  3087.                                     }
  3088.                                 }
  3089.                             }
  3090.                         }
  3091.  
  3092.                         // Remove the border of the piece, because it's the leftover from the bilinearization
  3093.                         // Set the new values for rotated piece
  3094.                         objlist_enum.Current.Value[0] = ++corners[0];
  3095.                         objlist_enum.Current.Value[1] = ++corners[1];
  3096.                         objlist_enum.Current.Value[2] = --corners[2];
  3097.                         objlist_enum.Current.Value[3] = --corners[3];
  3098.                     } // End of If Sqr4 != 4
  3099.                 } // End of Obj_List Enum
  3100.             } // End of Unsafe
  3101.         } // End of Rotate Pieces
  3102.  
  3103.         public static double[] Scale_Piece(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy, double[] sqr, double sF, byte[] bckgrnd)
  3104.         {
  3105.             unsafe
  3106.             {
  3107.                 MIplImage m = img.MIplImage;
  3108.                 MIplImage m1 = imgCopy.MIplImage;
  3109.                 byte* dataPtr = (byte*)m.imageData.ToPointer(); // Pointer to the image
  3110.                 byte* dataPtrCopy = (byte*)m1.imageData.ToPointer(); // Pointer to the image
  3111.  
  3112.                 byte* px, pxCopy;
  3113.                 byte* a, b, c, d;
  3114.  
  3115.                 int width = img.Width;
  3116.                 int height = img.Height;
  3117.                 int nChan = m.nChannels; // number of channels - 3
  3118.                 int widthStep = m.widthStep;
  3119.                 int padding = m.widthStep - m.nChannels * m.width; // alinhament bytes (padding)
  3120.                 int x, y, w, h;
  3121.                 double xo, yo;
  3122.                 double j, k;
  3123.                 double blueS, greenS, redS;
  3124.                 double blueI, greenI, redI;
  3125.                 int xr, yr; // reduzido ?
  3126.  
  3127.                 w = (int)sqr[2] - (int)sqr[0] + 1;
  3128.                 h = (int)sqr[3] - (int)sqr[1] + 1;
  3129.  
  3130.                 if (sF > 1)
  3131.                 {
  3132.                     // Because we scale the piece according to it's relative (0, 0) position,
  3133.                     // the coordinates of the top left corner don't change.
  3134.                     sqr[2] = Math.Round(sqr[2] + (sF - 1) * w);
  3135.                     sqr[3] = Math.Round(sqr[3] + (sF - 1) * h);
  3136.                 }
  3137.  
  3138.                 if (nChan == 3)
  3139.                 {
  3140.                     for (y = (int)sqr[1]; y <= sqr[3]; y++)
  3141.                     {
  3142.                         for (x = (int)sqr[0]; x <= sqr[2]; x++)
  3143.                         {
  3144.                             // CANTO SUPERIOR ESQUERDO DA PEÇA
  3145.                             xo = x / sF + (sqr[0] - sqr[0] / sF);
  3146.                             yo = y / sF + (sqr[1] - sqr[1] / sF);
  3147.  
  3148.                             j = xo % 1; // parte decimal da coordenada em x
  3149.                             k = yo % 1; // parte decimal da coordenada em y
  3150.  
  3151.                             xr = (int)(xo - j);
  3152.                             yr = (int)(yo - k);
  3153.  
  3154.                             px = (dataPtr + y * widthStep + x * nChan);
  3155.                             // calcula endereço do pixel no ponto (x,y)
  3156.                             if ((xo >= 0 && xo < width) && (yo >= 0 && yo <= height))
  3157.                             {
  3158.                                 if (xo == width - 1)
  3159.                                     xr--;  // para não passar da imagem quando (xr + 1)
  3160.                                 if (yo == height - 1)
  3161.                                     yr--; // para não passar da imagem quando (yr + 1)
  3162.  
  3163.                                 pxCopy = (dataPtrCopy + yr * m.widthStep + xr * nChan);
  3164.  
  3165.                                 a = (pxCopy);
  3166.                                 b = (pxCopy + nChan);
  3167.                                 c = (pxCopy + widthStep);
  3168.                                 d = (pxCopy + nChan + widthStep);
  3169.  
  3170.                                 if (x == sqr[2])
  3171.                                 {
  3172.                                     b = (pxCopy);
  3173.                                     d = (pxCopy + widthStep);
  3174.                                 }
  3175.                                 if (y == sqr[3])
  3176.                                 {
  3177.                                     c = (pxCopy);
  3178.                                     d = (pxCopy + nChan);
  3179.                                 }
  3180.                                 if (x == sqr[2] && y == sqr[3]) d = (pxCopy);
  3181.  
  3182.                                 // Bx+j,y = (1 - j) * Bx,y + j * Bx+1,y
  3183.                                 blueS = (1 - j) * a[0] + j * b[0];
  3184.                                 greenS = (1 - j) * a[1] + j * b[1];
  3185.                                 redS = (1 - j) * a[2] + j * b[2];
  3186.                                 // Bx+j,y+1 = (1 - j) * Bx,y+1 + j * Bx+1,y+1
  3187.                                 blueI = (1 - j) * c[0] + j * d[0];
  3188.                                 greenI = (1 - j) * c[1] + j * d[1];
  3189.                                 redI = (1 - j) * c[2] + j * d[2];
  3190.  
  3191.                                 // Bx+j,y+k = (1 - k) * Bx+j,y + k * Bx+j,y+1
  3192.                                 px[0] = (byte)(Math.Round((1 - k) * blueS + k * blueI));
  3193.                                 px[1] = (byte)(Math.Round((1 - k) * greenS + k * greenI));
  3194.                                 px[2] = (byte)(Math.Round((1 - k) * redS + k * redI));
  3195.                             }
  3196.                             else
  3197.                             {
  3198.                                 px[0] = 0;
  3199.                                 px[1] = 0;
  3200.                                 px[2] = 0;
  3201.                             }
  3202.                         }
  3203.                     }
  3204.  
  3205.                     // Copy resulted image from imgFinal back to imgCopy
  3206.                     for (y = (int)sqr[1]; y <= sqr[3]; y++)
  3207.                     {
  3208.                         for (x = (int)sqr[0]; x <= sqr[2]; x++)
  3209.                         {
  3210.                             px = (dataPtr + y * widthStep + x * nChan);
  3211.                             pxCopy = (dataPtrCopy + y * m.widthStep + x * nChan);
  3212.  
  3213.                             pxCopy[0] = px[0];
  3214.                             pxCopy[1] = px[1];
  3215.                             pxCopy[2] = px[2];
  3216.                         }
  3217.                     }
  3218.  
  3219.                     // Clean the image from imgFinal
  3220.                     ClearTrace(img, sqr, bckgrnd);
  3221.                 } // End of nChan = 3
  3222.  
  3223.                 return sqr;
  3224.             } // End of Unsafe
  3225.         } // End of Scale Piece Bilinear
  3226.  
  3227.         public static void ClearTrace(Image<Bgr, byte> img, double[] sqr, byte[] bckgrd)
  3228.         {
  3229.             unsafe
  3230.             {
  3231.                 MIplImage m = img.MIplImage;
  3232.                 byte* dataPtr = (byte*)m.imageData.ToPointer(); // Pointer to the image
  3233.                 byte* px;
  3234.  
  3235.                 int widthStep = m.widthStep;
  3236.                 int nChan = m.nChannels; // number of channels - 3
  3237.                 int x, y;
  3238.  
  3239.                 if (nChan == 3)
  3240.                 {
  3241.                     for (y = (int)sqr[1]; y <= sqr[3]; y++)
  3242.                     {
  3243.                         for (x = (int)sqr[0]; x <= sqr[2]; x++)
  3244.                         {
  3245.                             px = (dataPtr + y * widthStep + x * nChan);
  3246.  
  3247.                             px[0] = bckgrd[0];
  3248.                             px[1] = bckgrd[1];
  3249.                             px[2] = bckgrd[2];
  3250.  
  3251.                         } // End of For X
  3252.                     } // End of For Y
  3253.                 } // End of nChan = 3
  3254.             } // End of Unsafe
  3255.         } // End of Clear Trace
  3256.  
  3257.         public static void ClearImage(Image<Bgr, byte> img)
  3258.         {
  3259.             unsafe
  3260.             {
  3261.                 MIplImage m = img.MIplImage;
  3262.                 byte* dataPtr = (byte*)m.imageData.ToPointer(); // Pointer to the image
  3263.  
  3264.                 int width = img.Width;
  3265.                 int height = img.Height;
  3266.                 int widthStep = m.widthStep;
  3267.                 int nChan = m.nChannels; // number of channels - 3
  3268.                 int padding = widthStep - nChan * width;
  3269.                 int x, y;
  3270.  
  3271.                 byte[] bckgrnd = new byte[3] { dataPtr[0], dataPtr[1], dataPtr[2] };
  3272.  
  3273.                 if (nChan == 3) // image in RGB
  3274.                 {
  3275.                     for (y = 0; y < height; y++)
  3276.                     {
  3277.                         for (x = 0; x < width; x++)
  3278.                         {
  3279.                             dataPtr[0] = bckgrnd[0];
  3280.                             dataPtr[1] = bckgrnd[1];
  3281.                             dataPtr[2] = bckgrnd[2];
  3282.  
  3283.                             dataPtr += nChan;
  3284.                         }
  3285.                         dataPtr += padding;
  3286.                     }
  3287.                 } // End of nChan = 3
  3288.             } // End of Unsafe
  3289.         } // End of ClearImage
  3290.  
  3291.         // To Do - Remove one iteration
  3292.         public static int[,] Classification(Image<Bgr, byte> img, bool adj8, bool show_result)
  3293.         {
  3294.             unsafe
  3295.             {
  3296.                 Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
  3297.                 Trace.AutoFlush = true;
  3298.                 Trace.Indent();
  3299.  
  3300.                 MIplImage d = img.MIplImage;
  3301.                 byte* dataPtr = (byte*)d.imageData.ToPointer();   // Pointer to the final image
  3302.  
  3303.                 int w = img.Width;
  3304.                 int h = img.Height;
  3305.                 int nChan = d.nChannels;
  3306.                 int widthStep = d.widthStep;
  3307.                 int padding = widthStep - nChan * w;
  3308.                 int x, y;
  3309.  
  3310.                 int label_index = 0;
  3311.                 int[,] labels = new int[h, w];
  3312.  
  3313.                 int px_label, neig_smaller_label;
  3314.                 int[] neighbors = new int[4];
  3315.  
  3316.                 Dictionary<int, int> conflicts_list = new Dictionary<int, int>();
  3317.  
  3318.                 // Convert Background (0,0) to Gray
  3319.                 byte gray, bckgrnd_gray;
  3320.  
  3321.                 // Classification
  3322.                 if (nChan == 3)
  3323.                 {
  3324.                     bckgrnd_gray = (byte)Math.Round((dataPtr[0] + dataPtr[1] + dataPtr[2]) / 3.0);       // Inner Testing Background px_label
  3325.  
  3326.                     // Label Array Init
  3327.                     for (y = 0; y < h; y++)
  3328.                     {
  3329.                         for (x = 0; x < w; x++)
  3330.                         {
  3331.                             // Convert Selection to Gray
  3332.                             gray = (byte)Math.Round((dataPtr[0] + dataPtr[1] + dataPtr[2]) / 3.0);
  3333.  
  3334.                             // Label
  3335.                             if (gray == bckgrnd_gray)
  3336.                                 labels[y, x] = int.MaxValue;
  3337.                             else
  3338.                                 labels[y, x] = ++label_index;
  3339.  
  3340.                             dataPtr += nChan;
  3341.                         }
  3342.                         dataPtr += padding;
  3343.                     } // End of Labeling Array
  3344.  
  3345.                     // Core
  3346.                     for (y = 1; y < h - 1; y++)
  3347.                     {
  3348.                         for (x = 1; x < w - 1; x++)
  3349.                         {
  3350.                             px_label = labels[y, x];       // Get Label
  3351.                             if (px_label != int.MaxValue)
  3352.                             {
  3353.                                 // Not background (represented by MaxValueInt)
  3354.                                 neig_smaller_label = px_label;
  3355.  
  3356.                                 if (adj8)
  3357.                                     neighbors = new int[] { labels[y - 1, x - 1], labels[y - 1, x], labels[y - 1, x + 1], labels[y, x - 1], labels[y, x + 1], labels[y + 1, x - 1], labels[y + 1, x], labels[y + 1, x + 1] };   // Form 8_adj neighborhood
  3358.                                 else
  3359.                                     neighbors = new int[] { labels[y, x - 1], labels[y, x + 1], labels[y + 1, x], labels[y - 1, x] };   // Form 4_adj neighborhood
  3360.  
  3361.                                 // Run Neighborhood || Aux Value represents the actual smallest px_label that can exist in the neighborhood, a px_label of 0 only exists on the first run of if no neighbor is smaller
  3362.                                 for (int j = 0; j < neighbors.Length; j++)
  3363.                                 {
  3364.                                     if (neighbors[j] != int.MaxValue && neighbors[j] < px_label)
  3365.                                     {
  3366.                                         // Neighbor is not background and is smaller than current label
  3367.                                         if (neig_smaller_label == px_label)
  3368.                                         {
  3369.                                             // No Conflict - Aux gets the px_label of the neighbor (that is smaller)
  3370.                                             neig_smaller_label = neighbors[j];
  3371.                                         }
  3372.                                         else if (neig_smaller_label != neighbors[j])
  3373.                                         {
  3374.                                             // Smaller label exists | There is a conflict | However, the neighbor label must be different than the current lowest.
  3375.                                             // To create conflict, biggest value goes in the first position followed by the smallest
  3376.  
  3377.                                             int key, value;
  3378.  
  3379.                                             if (neig_smaller_label > neighbors[j])
  3380.                                             {
  3381.                                                 key = neig_smaller_label;
  3382.                                                 value = neighbors[j];
  3383.                                             }
  3384.                                             else
  3385.                                             {
  3386.                                                 key = neighbors[j];
  3387.                                                 value = neig_smaller_label;
  3388.                                             }
  3389.  
  3390.                                             if (!conflicts_list.TryGetValue(key, out int aux_value))
  3391.                                                 conflicts_list.Add(key, value); // Add conflict to list
  3392.                                             else
  3393.                                             {
  3394.                                                 // Conflict already exists - Create indirect conflict           **** VERIFY IF IT EVER HAPPENS
  3395.                                                 if (aux_value > value && !conflicts_list.ContainsKey(aux_value))
  3396.                                                     conflicts_list.Add(aux_value, value);
  3397.                                                 else if (value > aux_value && !conflicts_list.ContainsKey(value))
  3398.                                                     conflicts_list.Add(value, aux_value);
  3399.                                             }
  3400.  
  3401.                                             neig_smaller_label = value;   // neig_smaller_label now has the smallest label again.
  3402.                                         }
  3403.                                     }
  3404.                                 } // End of Neighborhood
  3405.  
  3406.                                 labels[y, x] = neig_smaller_label;       // Assign to label                    
  3407.                             } // End of Label != Backgrond
  3408.                         }
  3409.                     } // End of Core
  3410.  
  3411.                     // Resolve Conflicts
  3412.                     for (y = 0; y < h; y++)
  3413.                     {
  3414.                         for (x = 0; x < w; x++)
  3415.                         {
  3416.                             while (conflicts_list.TryGetValue(labels[y, x], out px_label))
  3417.                                 labels[y, x] = px_label;        // Replace Conflicts
  3418.                         }
  3419.                     } // End of Resolve Conflicts
  3420.  
  3421.                     // Debug
  3422.                     if (show_result)
  3423.                     {
  3424.                         dataPtr = (byte*)d.imageData.ToPointer();
  3425.                         for (y = 0; y < h; y++)
  3426.                         {
  3427.                             for (x = 0; x < w; x++)
  3428.                             {
  3429.                                 px_label = labels[y, x];
  3430.                                 if (px_label == int.MaxValue)
  3431.                                 {
  3432.                                     // Background
  3433.                                     dataPtr[0] = 0;
  3434.                                     dataPtr[1] = 0;
  3435.                                     dataPtr[2] = 0;
  3436.                                 }
  3437.                                 else
  3438.                                 {
  3439.                                     // Label
  3440.                                     if ((byte)px_label < 150)
  3441.                                         px_label += 100;
  3442.                                     dataPtr[0] = (byte)px_label;
  3443.                                     dataPtr[1] = (byte)px_label;
  3444.                                     dataPtr[2] = (byte)px_label;
  3445.                                 }
  3446.                                 dataPtr += nChan;
  3447.                             }
  3448.                             dataPtr += padding;
  3449.                         }
  3450.                     } // End of Show Result
  3451.                     return labels;
  3452.                 } // End of nChan = 3
  3453.                 return null;
  3454.             } // End of Unsafe
  3455.         } // End of Classification_8adj
  3456.  
  3457.         static public Dictionary<int, double[]> FindCorners(int[,] labels, int w, int h)
  3458.         {
  3459.             unsafe
  3460.             {
  3461.                 int x, y;
  3462.                 int label;
  3463.                 Dictionary<int, double[]> obj_list = new Dictionary<int, double[]>();
  3464.                 double[] corner;
  3465.  
  3466.                 for (y = 0; y < h; y++)
  3467.                 {
  3468.                     for (x = 0; x < w; x++)
  3469.                     {
  3470.                         label = labels[y, x];
  3471.  
  3472.                         if (label != int.MaxValue)
  3473.                         {
  3474.                             if (obj_list.TryGetValue(label, out corner))
  3475.                             {
  3476.                                 // Label found | Change square bigger/small x,y
  3477.                                 if (x < corner[0])
  3478.                                     corner[0] = x;
  3479.  
  3480.                                 if (y < corner[1])
  3481.                                     corner[1] = y;
  3482.  
  3483.                                 if (x > corner[2])
  3484.                                     corner[2] = x;
  3485.  
  3486.                                 if (y > corner[3])
  3487.                                     corner[3] = y;
  3488.  
  3489.                                 obj_list.Remove(label);
  3490.                                 obj_list.Add(label, corner);
  3491.                             }
  3492.                             else
  3493.                             {
  3494.                                 // New Label | Add new Labeled Square to list
  3495.                                 corner = new double[6];
  3496.                                 corner[0] = x; // Top Left X        | minor_x
  3497.                                 corner[1] = y; // Top Left Y        | minor_y
  3498.                                 corner[2] = x; // Bottom Right X    | bigger_x
  3499.                                 corner[3] = y; // Bottom Right Y    | bigger_y
  3500.                                 corner[5] = 0; // In the original
  3501.                                 obj_list.Add(label, corner);
  3502.                             }
  3503.                         } // End of Label != int.MaxValue
  3504.                     }
  3505.                 }
  3506.  
  3507.                 // Verify if squares are rotated
  3508.                 Dictionary<int, double[]>.Enumerator obj_enum = obj_list.GetEnumerator();
  3509.  
  3510.                 while (obj_enum.MoveNext())
  3511.                 {
  3512.                     x = (int)obj_enum.Current.Value[0];
  3513.                     y = (int)obj_enum.Current.Value[1];
  3514.                     label = labels[(int)y, (int)x];
  3515.  
  3516.                     if (label == int.MaxValue)
  3517.                     {
  3518.                         int x_right = x;
  3519.                         int y_below = y;
  3520.  
  3521.                         // Y
  3522.                         do
  3523.                         {
  3524.                             y_below++;
  3525.                         } while (labels[(int)y_below, (int)x] == int.MaxValue);
  3526.  
  3527.                         // X
  3528.                         do
  3529.                         {
  3530.                             x_right++;
  3531.                         } while (labels[(int)y, (int)x_right] == int.MaxValue);
  3532.  
  3533.                         // Object is rotate, must infer rotation angle
  3534.                         double o = y_below - y;
  3535.                         double a = x_right - x;
  3536.  
  3537.                         obj_enum.Current.Value[4] = (Math.Atan(o / a) * 180) / Math.PI;
  3538.  
  3539.                     }
  3540.                     else
  3541.                     {
  3542.                         // Object is not rotated, angle is zero
  3543.                         obj_enum.Current.Value[4] = 0;
  3544.                     }
  3545.                 }
  3546.  
  3547.                 return obj_list;
  3548.             } // End of Unsafe
  3549.         } // End of FindCorners
  3550.        
  3551.         static public Dictionary<Tuple<int, int>, int[]> EdgeComparison(Image<Bgr, byte> img, Image<Bgr, byte> imgFinal, Dictionary<int, double[]> obj_list, Boolean runDiffSizeEdges)
  3552.         {
  3553.             unsafe
  3554.             {
  3555.                 MIplImage copy = img.MIplImage;
  3556.                 MIplImage final = imgFinal.MIplImage;
  3557.                 byte* dataPtr = (byte*)copy.imageData.ToPointer();   // Pointer to the Image
  3558.                 byte* dataPtrFinal = (byte*)final.imageData.ToPointer();   // Pointer to the Image
  3559.                 byte* img1Ptr, img2Ptr;
  3560.                 byte* px, px_copy;
  3561.                 int nChan = copy.nChannels;
  3562.                 int widthStep = copy.widthStep;
  3563.  
  3564.                 List<int> keyList = new List<int>(obj_list.Keys);
  3565.                 int[] labelArray = new int[keyList.Count];
  3566.  
  3567.                 Dictionary<Tuple<int, int>, int[]> piece_resemblance = new Dictionary<Tuple<int, int>, int[]>();
  3568.                 Tuple<int, int> piecesCombination;      // key piece_resemblance
  3569.                                                         //int[] edgeDiff = new int[4];            // value piece_resemblance
  3570.  
  3571.                 double edgeSize1, edgeSize2;
  3572.                 double n, m, u, v;
  3573.                 int i, j, t;
  3574.                 int gray1, gray2;
  3575.  
  3576.                 i = 0;
  3577.                 // Pass label values from list to array
  3578.                 foreach (int keyIterator in keyList)
  3579.                 {
  3580.                     labelArray[i] = keyIterator;
  3581.                     i++;
  3582.                 }
  3583.  
  3584.                 // ------------------------------------------------------------------------
  3585.                 // Total combinations : n * (n - 1) / 2
  3586.                 // Notes:   Ensures i != j always (a piece is never compared with itself);
  3587.                 //          j is always ahead of i;
  3588.                 //          The last object is never analysed by i;
  3589.                 // ------------------------------------------------------------------------
  3590.  
  3591.                 for (i = 0; i < labelArray.Length - 1; i++)
  3592.                 {
  3593.                     for (j = i + 1; j < labelArray.Length; j++)
  3594.                     {
  3595.                         // Because the labels are always in increasing order, labelArray[i] < labelArray[j] always happens. But just in case...
  3596.                         if (labelArray[i] < labelArray[j])
  3597.                             piecesCombination = new Tuple<int, int>(labelArray[i], labelArray[j]);
  3598.                         else
  3599.                             piecesCombination = new Tuple<int, int>(labelArray[j], labelArray[i]);
  3600.  
  3601.                         // Get the corners for each object
  3602.                         obj_list.TryGetValue(piecesCombination.Item1, out double[] corners1);
  3603.                         obj_list.TryGetValue(piecesCombination.Item2, out double[] corners2);
  3604.  
  3605.                         // Edge difference created here to generate a 'new' variable. Otherwise, it would overwrite the other edges.
  3606.                         // Init with max contrast
  3607.                         // [0] Left edge; [1] Right edge; [2] Top edge; [3] Bottom edge;
  3608.                         int[] edgeDiff = new int[4] { 255, 255, 255, 255 };            // value piece_resemblance
  3609.  
  3610.                         //img1Ptr = (corners1[5] == 1) ? dataPtrFinal : dataPtr;
  3611.                         //img2Ptr = (corners2[5] == 1) ? dataPtrFinal : dataPtr;
  3612.  
  3613.                         // ----------------------------------------------------------   Left & Right edges
  3614.                         //   Left edges
  3615.                         edgeSize1 = corners1[3] - corners1[1] + 1;
  3616.                         edgeSize2 = corners2[3] - corners2[1] + 1;
  3617.  
  3618.                         if (edgeSize1 == edgeSize2) // Level2. Length of edge must be the same
  3619.                         {
  3620.                             for (t = 0; t < edgeSize1; t++)  // Iterate along the edge
  3621.                             {
  3622.                                 n = corners1[1];
  3623.                                 v = corners2[1];
  3624.  
  3625.                                 // Left side x -> Right side x
  3626.                                 m = corners1[0];
  3627.                                 u = corners2[2];
  3628.  
  3629.                                 px = dataPtr + (int)(n + t) * widthStep + (int)m * nChan;
  3630.                                 gray1 = (int)Math.Round((px[0] + px[1] + px[2]) / 3.0);
  3631.                                 px = dataPtr + (int)(v + t) * widthStep + (int)u * nChan;
  3632.                                 gray2 = (int)Math.Round((px[0] + px[1] + px[2]) / 3.0);
  3633.  
  3634.                                 edgeDiff[0] += Math.Abs(gray1 - gray2);
  3635.  
  3636.                                 // Right side x -> Left side x
  3637.                                 m = corners1[2];
  3638.                                 u = corners2[0];
  3639.  
  3640.                                 px = dataPtr + (int)(n + t) * widthStep + (int)m * nChan;
  3641.                                 gray1 = (int)Math.Round((px[0] + px[1] + px[2]) / 3.0);
  3642.                                 px = dataPtr + (int)(v + t) * widthStep + (int)u * nChan;
  3643.                                 gray2 = (int)Math.Round((px[0] + px[1] + px[2]) / 3.0);
  3644.  
  3645.                                 edgeDiff[1] += Math.Abs(gray1 - gray2);
  3646.                             }
  3647.                             // Get the average difference of values between edges
  3648.                             edgeDiff[0] = (int)Math.Round((edgeDiff[0] - 255) / edgeSize1); // [0 ... 255]
  3649.                             edgeDiff[1] = (int)Math.Round((edgeDiff[1] - 255) / edgeSize1); // [0 ... 255]
  3650.                         }
  3651.                         else if (runDiffSizeEdges)
  3652.                         {
  3653.                             // Different Sized Edges
  3654.                             // Discover smaller Edge
  3655.                             double sF, edgeStatic;
  3656.                             double[] sqr_zoom, sqr_static;
  3657.  
  3658.                             if (edgeSize1 > edgeSize2)
  3659.                             {
  3660.                                 // Smaller Edge1
  3661.                                 sF = edgeSize1 / edgeSize2;
  3662.                                 sqr_zoom = corners2;
  3663.                                 sqr_static = corners1;
  3664.                                 edgeStatic = edgeSize1;
  3665.                                 // img1Ptr has the static
  3666.                                 img1Ptr = (corners1[5] == 1) ? dataPtrFinal : dataPtr;
  3667.                                 img2Ptr = (corners2[5] == 1) ? dataPtrFinal : dataPtr;
  3668.                             }
  3669.                             else
  3670.                             {
  3671.                                 // Smaller Edge2
  3672.                                 sF = edgeSize2 / edgeSize1;
  3673.                                 sqr_zoom = corners1;
  3674.                                 sqr_static = corners2;
  3675.                                 edgeStatic = edgeSize2;
  3676.                                 // img1Ptr has the static
  3677.                                 img1Ptr = (corners2[5] == 1) ? dataPtrFinal : dataPtr;
  3678.                                 img2Ptr = (corners1[5] == 1) ? dataPtrFinal : dataPtr;
  3679.                             }
  3680.  
  3681.                             // Zoom Smallest Edge while comparing with the static one
  3682.                             for (t = 0; t < edgeStatic; t++)  // Iterate along the edge
  3683.                             {
  3684.                                 n = sqr_static[1];
  3685.                                 v = sqr_zoom[1];
  3686.  
  3687.                                 // Left side x -> Right side x
  3688.                                 m = sqr_static[0];
  3689.                                 u = sqr_zoom[2];
  3690.  
  3691.                                 // Static
  3692.                                 px = img1Ptr + (int)(n + t) * widthStep + (int)m * nChan;
  3693.                                 gray1 = (int)Math.Round((px[0] + px[1] + px[2]) / 3.0);
  3694.  
  3695.                                 // Zoom
  3696.                                 px = img2Ptr + (int)(v + t * (1 / sF)) * widthStep + (int)u * nChan;
  3697.                                 gray2 = (int)Math.Round((px[0] + px[1] + px[2]) / 3.0);
  3698.  
  3699.                                 edgeDiff[0] += Math.Abs(gray1 - gray2);
  3700.  
  3701.                                 // Right side x -> Left side x
  3702.                                 m = sqr_static[2];
  3703.                                 u = sqr_zoom[0];
  3704.  
  3705.                                 // Static
  3706.                                 px = img1Ptr + (int)(n + t) * widthStep + (int)m * nChan;
  3707.                                 gray1 = (int)Math.Round((px[0] + px[1] + px[2]) / 3.0);
  3708.  
  3709.                                 // Zoom
  3710.                                 px = img2Ptr + (int)(v + t * (1 / sF)) * widthStep + (int)u * nChan;
  3711.                                 gray2 = (int)Math.Round((px[0] + px[1] + px[2]) / 3.0);
  3712.  
  3713.                                 edgeDiff[1] += Math.Abs(gray1 - gray2);
  3714.                             }
  3715.                             // Get the average difference of values between edges
  3716.                             edgeDiff[0] = (int)Math.Round((edgeDiff[0] - 255) / edgeStatic); // [0 ... 255]
  3717.                             edgeDiff[1] = (int)Math.Round((edgeDiff[1] - 255) / edgeStatic); // [0 ... 255]
  3718.                         }
  3719.  
  3720.                         // ----------------------------------------------------------   Top & Bottom edges
  3721.                         //   Top edges
  3722.                         edgeSize1 = corners1[2] - corners1[0] + 1;
  3723.                         edgeSize2 = corners2[2] - corners2[0] + 1;
  3724.  
  3725.                         if (edgeSize1 == edgeSize2) // Level2. Length of edge must be the same
  3726.                         {
  3727.                             // Equal Edges
  3728.                             for (t = 0; t < edgeSize1; t++)  // Iterate along the edge
  3729.                             {
  3730.                                 m = corners1[0];
  3731.                                 u = corners2[0];
  3732.  
  3733.                                 // Top side y -> Bottom side y
  3734.                                 n = corners1[1];
  3735.                                 v = corners2[3];
  3736.  
  3737.                                 px = dataPtr + (int)n * widthStep + (int)(m + t) * nChan;
  3738.                                 gray1 = (int)Math.Round((px[0] + px[1] + px[2]) / 3.0);
  3739.                                 px = dataPtr + (int)v * widthStep + (int)(u + t) * nChan;
  3740.                                 gray2 = (int)Math.Round((px[0] + px[1] + px[2]) / 3.0);
  3741.  
  3742.                                 edgeDiff[2] += Math.Abs(gray1 - gray2);
  3743.  
  3744.                                 // Bottom side y -> Top side y
  3745.                                 n = corners1[3];
  3746.                                 v = corners2[1];
  3747.  
  3748.                                 px = dataPtr + (int)n * widthStep + (int)(m + t) * nChan;
  3749.                                 gray1 = (int)Math.Round((px[0] + px[1] + px[2]) / 3.0);
  3750.                                 px = dataPtr + (int)v * widthStep + (int)(u + t) * nChan;
  3751.                                 gray2 = (int)Math.Round((px[0] + px[1] + px[2]) / 3.0);
  3752.  
  3753.                                 edgeDiff[3] += Math.Abs(gray1 - gray2);
  3754.                             }
  3755.                             // Get the average difference of values between edges
  3756.                             edgeDiff[2] = (int)Math.Round((edgeDiff[2] - 255) / edgeSize1); // [0 ... 255]
  3757.                             edgeDiff[3] = (int)Math.Round((edgeDiff[3] - 255) / edgeSize1); // [0 ... 255]
  3758.                         }
  3759.                         else if (runDiffSizeEdges)
  3760.                         {
  3761.                             // Different Sized Edges
  3762.                             // Discover smaller Edge
  3763.                             double sF, edgeStatic;
  3764.                             double[] sqr_zoom, sqr_static;
  3765.  
  3766.                             if (edgeSize1 > edgeSize2)
  3767.                             {
  3768.                                 // Smaller Edge1
  3769.                                 sF = edgeSize1 / edgeSize2;
  3770.                                 sqr_zoom = corners2;
  3771.                                 sqr_static = corners1;
  3772.                                 edgeStatic = edgeSize1;
  3773.                                 // img1Ptr has the static
  3774.                                 img1Ptr = (corners1[5] == 1) ? dataPtrFinal : dataPtr;
  3775.                                 img2Ptr = (corners2[5] == 1) ? dataPtrFinal : dataPtr;
  3776.                             }
  3777.                             else
  3778.                             {
  3779.                                 // Smaller Edge2
  3780.                                 sF = edgeSize2 / edgeSize1;
  3781.                                 sqr_zoom = corners1;
  3782.                                 sqr_static = corners2;
  3783.                                 edgeStatic = edgeSize2;
  3784.                                 // img1Ptr has the static
  3785.                                 img1Ptr = (corners2[5] == 1) ? dataPtrFinal : dataPtr;
  3786.                                 img2Ptr = (corners1[5] == 1) ? dataPtrFinal : dataPtr;
  3787.                             }
  3788.  
  3789.                             // Zoom Smallest Edge while comparing with the static one
  3790.                             for (t = 0; t < edgeStatic; t++)  // Iterate along the edge
  3791.                             {
  3792.                                 m = sqr_static[0];
  3793.                                 u = sqr_zoom[0];
  3794.  
  3795.                                 // Top side y -> Bottom side y
  3796.                                 n = sqr_static[1];
  3797.                                 v = sqr_zoom[3];
  3798.  
  3799.                                 // Static
  3800.                                 px = img1Ptr + (int)n * widthStep + (int)(m + t) * nChan;
  3801.                                 gray1 = (int)Math.Round((px[0] + px[1] + px[2]) / 3.0);
  3802.  
  3803.                                 // Zoom
  3804.                                 px = img2Ptr + (int)v * widthStep + (int)(u + t * (1 / sF)) * nChan;
  3805.                                 gray2 = (int)Math.Round((px[0] + px[1] + px[2]) / 3.0);
  3806.  
  3807.                                 edgeDiff[2] += Math.Abs(gray1 - gray2);
  3808.  
  3809.                                 // Bottom side y -> Top side y
  3810.                                 n = sqr_static[3];
  3811.                                 v = sqr_zoom[1];
  3812.  
  3813.                                 // Static
  3814.                                 px = img1Ptr + (int)n * widthStep + (int)(m + t) * nChan;
  3815.                                 gray1 = (int)Math.Round((px[0] + px[1] + px[2]) / 3.0);
  3816.  
  3817.                                 // Zoom
  3818.                                 px = img2Ptr + (int)v * widthStep + (int)(u + t * (1 / sF)) * nChan;
  3819.                                 gray2 = (int)Math.Round((px[0] + px[1] + px[2]) / 3.0);
  3820.  
  3821.                                 edgeDiff[3] += Math.Abs(gray1 - gray2);
  3822.                             }
  3823.                             // Get the average difference of values between edges
  3824.                             edgeDiff[2] = (int)Math.Round((edgeDiff[2] - 255) / edgeStatic); // [0 ... 255]
  3825.                             edgeDiff[3] = (int)Math.Round((edgeDiff[3] - 255) / edgeStatic); // [0 ... 255]
  3826.                         }
  3827.  
  3828.                         // Store comparison with edge difference
  3829.                         piece_resemblance.Add(piecesCombination, edgeDiff);
  3830.                     }
  3831.                 }
  3832.                 return piece_resemblance;
  3833.             }
  3834.         } // End of Edge Comparison
  3835.  
  3836.         static public Dictionary<Tuple<int, int>, int[]> EdgeRecalculation(Image<Bgr, byte> img, Image<Bgr, byte> imgCpy, Dictionary<int, double[]> obj_list, Dictionary<Tuple<int, int>, int[]> piece_resemblance, int macro, Tuple<int, int> micro)
  3837.         {
  3838.             unsafe
  3839.             {
  3840.                 MIplImage final = img.MIplImage;
  3841.                 MIplImage copy = imgCpy.MIplImage;
  3842.                 byte* dataPtr = (byte*)final.imageData.ToPointer();   // Pointer to the final image
  3843.                 byte* dataPtrCpy = (byte*)copy.imageData.ToPointer();   // Pointer to the original image
  3844.                 byte* sqr1Ptr, sqr2Ptr, AuxPtr;
  3845.                 byte* dataPtrStatic = dataPtr;
  3846.                 int nChan = final.nChannels;
  3847.                 int widthStep = final.widthStep;
  3848.  
  3849.                 Tuple<int, int> piecesCombination;      // key piece_resemblance
  3850.                 List<int> keyList = new List<int>(obj_list.Keys);
  3851.                 int[] labelArray = new int[keyList.Count];
  3852.  
  3853.                 double edgeSize1, edgeSize2;
  3854.                 double n, m, u, v;
  3855.                 int i, t;
  3856.                 int gray1, gray2;
  3857.  
  3858.                 if (obj_list.Count < 2)
  3859.                     return null;
  3860.  
  3861.                 foreach (Tuple<int, int> pieceIteration in piece_resemblance.Keys.ToList())
  3862.                 {
  3863.                     if (pieceIteration.Item1 == micro.Item1
  3864.                             || pieceIteration.Item1 == micro.Item2
  3865.                             || pieceIteration.Item2 == micro.Item1
  3866.                             || pieceIteration.Item2 == micro.Item2)
  3867.                         piece_resemblance.Remove(pieceIteration);
  3868.                 }
  3869.  
  3870.                 i = 0;
  3871.                 // Pass label values from list to array
  3872.                 foreach (int keyIterator in keyList)
  3873.                 {
  3874.                     labelArray[i] = keyIterator;
  3875.                     i++;
  3876.                 }
  3877.  
  3878.                 for (i = 0; i < labelArray.Length; i++)
  3879.                 {
  3880.                     if (labelArray[i] != macro)
  3881.                     {
  3882.                         if (labelArray[i] < macro)
  3883.                             piecesCombination = new Tuple<int, int>(labelArray[i], macro);
  3884.                         else
  3885.                             piecesCombination = new Tuple<int, int>(macro, labelArray[i]);
  3886.  
  3887.                         // Get the corners for each object
  3888.                         obj_list.TryGetValue(piecesCombination.Item1, out double[] corners1);
  3889.                         obj_list.TryGetValue(piecesCombination.Item2, out double[] corners2);
  3890.  
  3891.                         if (corners1[5] == 0)
  3892.                             sqr1Ptr = dataPtrCpy;
  3893.                         else
  3894.                             sqr1Ptr = dataPtr;
  3895.  
  3896.                         if (corners2[5] == 0)
  3897.                             sqr2Ptr = dataPtrCpy;
  3898.                         else
  3899.                             sqr2Ptr = dataPtr;
  3900.  
  3901.                         // Edge difference created here to generate a 'new' variable. Otherwise, it would overwrite the other edges.
  3902.                         // Init with max contrast
  3903.                         // [0] Left edge; [1] Right edge; [2] Top edge; [3] Bottom edge;
  3904.                         int[] edgeDiff = new int[4] { 255, 255, 255, 255 };            // value piece_resemblance
  3905.  
  3906.                         // ----------------------------------------------------------   Left & Right edges
  3907.                         //   Left edges
  3908.                         edgeSize1 = corners1[3] - corners1[1] + 1;
  3909.                         edgeSize2 = corners2[3] - corners2[1] + 1;
  3910.  
  3911.                         if (edgeSize1 == edgeSize2) // Level2. Length of edge must be the same
  3912.                         {
  3913.                             for (t = 0; t < edgeSize1; t++)  // Iterate along the edge
  3914.                             {
  3915.                                 n = corners1[1];
  3916.                                 v = corners2[1];
  3917.  
  3918.                                 // Left side x -> Right side x
  3919.                                 m = corners1[0];
  3920.                                 u = corners2[2];
  3921.  
  3922.                                 AuxPtr = sqr1Ptr + (int)(n + t) * widthStep + (int)m * nChan;
  3923.                                 gray1 = (int)Math.Round((AuxPtr[0] + AuxPtr[1] + AuxPtr[2]) / 3.0);
  3924.                                 AuxPtr = sqr2Ptr + (int)(v + t) * widthStep + (int)u * nChan;
  3925.                                 gray2 = (int)Math.Round((AuxPtr[0] + AuxPtr[1] + AuxPtr[2]) / 3.0);
  3926.  
  3927.                                 edgeDiff[0] += Math.Abs(gray1 - gray2);
  3928.  
  3929.                                 // Right side x -> Left side x
  3930.                                 m = corners1[2];
  3931.                                 u = corners2[0];
  3932.  
  3933.                                 AuxPtr = sqr1Ptr + (int)(n + t) * widthStep + (int)m * nChan;
  3934.                                 gray1 = (int)Math.Round((AuxPtr[0] + AuxPtr[1] + AuxPtr[2]) / 3.0);
  3935.                                 AuxPtr = sqr2Ptr + (int)(v + t) * widthStep + (int)u * nChan;
  3936.                                 gray2 = (int)Math.Round((AuxPtr[0] + AuxPtr[1] + AuxPtr[2]) / 3.0);
  3937.  
  3938.                                 edgeDiff[1] += Math.Abs(gray1 - gray2);
  3939.                             }
  3940.                             // Get the average difference of values between edges
  3941.                             edgeDiff[0] = (int)Math.Round((edgeDiff[0] - 255) / edgeSize1); // [0 ... 255]
  3942.                             edgeDiff[1] = (int)Math.Round((edgeDiff[1] - 255) / edgeSize1); // [0 ... 255]
  3943.                         }
  3944.  
  3945.                         // ----------------------------------------------------------   Top & Bottom edges
  3946.                         //   Top edges
  3947.                         edgeSize1 = corners1[2] - corners1[0] + 1;
  3948.                         edgeSize2 = corners2[2] - corners2[0] + 1;
  3949.  
  3950.                         if (edgeSize1 == edgeSize2) // Level2. Length of edge must be the same
  3951.                         {
  3952.                             for (t = 0; t < edgeSize1; t++)  // Iterate along the edge
  3953.                             {
  3954.                                 m = corners1[0];
  3955.                                 u = corners2[0];
  3956.  
  3957.                                 // Top side y -> Bottom side y
  3958.                                 n = corners1[1];
  3959.                                 v = corners2[3];
  3960.  
  3961.                                 AuxPtr = sqr1Ptr + (int)n * widthStep + (int)(m + t) * nChan;
  3962.                                 gray1 = (int)Math.Round((AuxPtr[0] + AuxPtr[1] + AuxPtr[2]) / 3.0);
  3963.                                 AuxPtr = sqr2Ptr + (int)v * widthStep + (int)(u + t) * nChan;
  3964.                                 gray2 = (int)Math.Round((AuxPtr[0] + AuxPtr[1] + AuxPtr[2]) / 3.0);
  3965.  
  3966.                                 edgeDiff[2] += Math.Abs(gray1 - gray2);
  3967.  
  3968.                                 // Bottom side y -> Top side y
  3969.                                 n = corners1[3];
  3970.                                 v = corners2[1];
  3971.  
  3972.                                 AuxPtr = sqr1Ptr + (int)n * widthStep + (int)(m + t) * nChan;
  3973.                                 gray1 = (int)Math.Round((AuxPtr[0] + AuxPtr[1] + AuxPtr[2]) / 3.0);
  3974.                                 AuxPtr = sqr2Ptr + (int)v * widthStep + (int)(u + t) * nChan;
  3975.                                 gray2 = (int)Math.Round((AuxPtr[0] + AuxPtr[1] + AuxPtr[2]) / 3.0);
  3976.  
  3977.                                 edgeDiff[3] += Math.Abs(gray1 - gray2);
  3978.                             }
  3979.                             // Get the average difference of values between edges
  3980.                             edgeDiff[2] = (int)Math.Round((edgeDiff[2] - 255) / edgeSize1); // [0 ... 255]
  3981.                             edgeDiff[3] = (int)Math.Round((edgeDiff[3] - 255) / edgeSize1); // [0 ... 255]
  3982.                         }
  3983.  
  3984.                         // Store comparison with edge difference
  3985.                         piece_resemblance.Add(piecesCombination, edgeDiff);
  3986.                     }
  3987.                 }
  3988.                 return piece_resemblance;
  3989.             }
  3990.         } // End of Edge Recalculation
  3991.  
  3992.         static public int DiscoverMacroCornerCoord(int[,] defaultMacroPos, double[] micro1, double[] micro2, int label1, int label2, out double cxm, out double cym)
  3993.         {
  3994.             int defaultPos = 0;
  3995.  
  3996.             // Verify if either micros are using default positions || If both are, micro1's position will have priority || If none are, fetch a new unused macro default position
  3997.             if (micro1[5] == 1)
  3998.             {
  3999.                 // Iterate defaultMacroPositions to find micro1's corner
  4000.                 while ((label1 != defaultMacroPos[defaultPos, 2]))
  4001.                 {
  4002.                     defaultPos++;
  4003.                 }
  4004.  
  4005.                 // If micro2 was also positioned in the macro img, vacate.
  4006.                 if (micro2[5] == 1)
  4007.                 {
  4008.                     int defaultPos_aux = 0;
  4009.                     while ((label2 != defaultMacroPos[defaultPos_aux, 2]))
  4010.                     {
  4011.                         defaultPos_aux++;
  4012.                     }
  4013.                     defaultMacroPos[defaultPos_aux, 2] = 0;     // Mark as unused
  4014.                 }
  4015.  
  4016.                 cym = defaultMacroPos[defaultPos, 0];
  4017.                 cxm = defaultMacroPos[defaultPos, 1];
  4018.                 defaultMacroPos[defaultPos, 2] = label1;      // Mark as used | Redudant since micro1 was already in that position
  4019.                 return defaultPos;
  4020.             }
  4021.             else if (micro2[5] == 1)
  4022.             {
  4023.                 // Iterate defaultMacroPositions to find micro2's corner
  4024.                 while ((label2 != defaultMacroPos[defaultPos, 2]))
  4025.                 {
  4026.                     defaultPos++;
  4027.                 }
  4028.  
  4029.                 cym = defaultMacroPos[defaultPos, 0];
  4030.                 cxm = defaultMacroPos[defaultPos, 1];
  4031.                 defaultMacroPos[defaultPos, 2] = label1;      // Mark as used | Redudant since micro2 was already in that position
  4032.                 return defaultPos;
  4033.             }
  4034.             else if (micro1[5] == 0 && micro2[5] == 0)
  4035.             {
  4036.                 // Iterate defaultMacroPositions to find the first unused position
  4037.                 while (defaultMacroPos[defaultPos, 2] != 0)
  4038.                 {
  4039.                     defaultPos++;
  4040.                 }
  4041.  
  4042.                 cym = defaultMacroPos[defaultPos, 0];
  4043.                 cxm = defaultMacroPos[defaultPos, 1];
  4044.                 defaultMacroPos[defaultPos, 2] = label1;      // Mark as used | Redudant since micro1 was already in that position
  4045.                 return defaultPos;
  4046.             }
  4047.             else
  4048.             {
  4049.                 cym = 0;
  4050.                 cxm = 0;
  4051.                 defaultPos = -1;    // Error, somehow...
  4052.                 return defaultPos;
  4053.             }
  4054.         } // End of Discover Macro Corner Coord
  4055.  
  4056.         static public void JoinPieces(Image<Bgr, byte> img, Image<Bgr, byte> imgCpy, Dictionary<int, double[]> obj_list)
  4057.         {
  4058.             unsafe
  4059.             {
  4060.                 Image<Bgr, byte> img_aux;
  4061.                 MIplImage d = img.MIplImage;
  4062.                 MIplImage c = imgCpy.MIplImage;
  4063.                 byte* dataPtr = (byte*)d.imageData.ToPointer();   // Pointer to the final image
  4064.                 byte* dataPtrCpy = (byte*)c.imageData.ToPointer();   // Pointer to the original image
  4065.  
  4066.                 byte[] bckgrnd = new byte[3] { dataPtr[0], dataPtr[1], dataPtr[2] };
  4067.  
  4068.                 int w = img.Width;
  4069.                 int h = img.Height;
  4070.  
  4071.                 // Divide the image in 4.
  4072.                 // 0 : x
  4073.                 // 1 : y
  4074.                 // 2 : label assigned   - 0 if not assigned
  4075.                 int[,] defaultMacroPos = new int[4, 3] { {0 , 0, 0},
  4076.                                                         {h-1 , w-1, 0},
  4077.                                                         {0 , w-1, 0},
  4078.                                                         {h-1 , 0, 0} };
  4079.                 int defaultPos;
  4080.  
  4081.                 if (obj_list.Count > 1)
  4082.                 {
  4083.                     // Clear ImgCpy - All pixels will be background
  4084.                     ClearImage(img);
  4085.  
  4086.                     // Compare all object edges with eachother.
  4087.                     Dictionary<Tuple<int, int>, int[]> piece_resemblance = EdgeComparison(imgCpy, img, obj_list, false);
  4088.  
  4089.                     // Merge All Pieces
  4090.                     while (obj_list.Count > 1)
  4091.                     {
  4092.                         Console.WriteLine("Outter While | Current Obj_Count: {0}", obj_list.Count);
  4093.  
  4094.  
  4095.                         // Merge All Pieces, that have the same edge size.
  4096.                         while (obj_list.Count > 1)
  4097.                         {
  4098.                             Console.WriteLine("Inner While | Current Obj_Count: {0}", obj_list.Count);
  4099.                             // Init Micro-cell combination variables
  4100.                             Tuple<int, int> microCellCombination = new Tuple<int, int>(0, 0);
  4101.                             int minContrast = 255;
  4102.                             int minContIndex = 0;
  4103.  
  4104.                             // Find the smallest value of contrast -- Find mergeable micro cells
  4105.                             foreach (var edgesIterator in piece_resemblance)
  4106.                             {
  4107.                                 for (int i = 0; i < edgesIterator.Value.Length; i++)
  4108.                                 {
  4109.                                     if (edgesIterator.Value[i] < minContrast)   // Save the index (corresponds to the edge), the contrast of such edge, and the key
  4110.                                     {
  4111.                                         minContIndex = i;
  4112.                                         minContrast = edgesIterator.Value[i];
  4113.                                         microCellCombination = edgesIterator.Key;
  4114.                                     }
  4115.                                 }
  4116.                             } // End of Find Smallest Value
  4117.  
  4118.                             // CIGANAGEM!!
  4119.                             // Threshold de 30, porque funca para todas as imagens.
  4120.                             // Na img 11.png, a semelhança entre 2 peças erradas é de 34 (entre 2 e 5: [0] = 37, [1] = 34), porque precisa da peça escalada no meio das duas
  4121.                             if (minContrast > 30)
  4122.                             {
  4123.                                 Console.WriteLine("No valid piece combination has been found, all remaining edges have different sizes");
  4124.                                 break;
  4125.                             }
  4126.  
  4127.                             Console.WriteLine("New Match: {0},{1}", microCellCombination.Item1, microCellCombination.Item2);
  4128.  
  4129.                             // Remove Micro Cells and add new Macro Cell
  4130.                             obj_list.TryGetValue(microCellCombination.Item1, out double[] old_micro1);
  4131.                             obj_list.TryGetValue(microCellCombination.Item2, out double[] old_micro2);
  4132.  
  4133.                             double[] new_micro1 = new double[6],
  4134.                                      new_micro2 = new double[6],
  4135.                                      macro = new double[6];
  4136.  
  4137.                             double w1 = old_micro1[2] - old_micro1[0] + 1,
  4138.                                 w2 = old_micro2[2] - old_micro2[0] + 1,
  4139.                                 h1 = old_micro1[3] - old_micro1[1] + 1,
  4140.                                 h2 = old_micro2[3] - old_micro2[1] + 1,
  4141.                                 wm = 0, hm = 0;
  4142.  
  4143.  
  4144.  
  4145.                             // Calculate new micro and macro coordinates with referencial 0,0
  4146.                             if (minContIndex == 0 || minContIndex == 2)
  4147.                             {
  4148.                                 if (minContIndex == 0)
  4149.                                 {
  4150.                                     // Left Edge - Equal height , Sum width
  4151.                                     wm = w1 + w2;
  4152.                                     hm = h1;
  4153.                                     new_micro1[0] = w2;
  4154.                                     new_micro1[1] = 0;
  4155.                                 }
  4156.                                 else if (minContIndex == 2)
  4157.                                 {
  4158.                                     // Top Edge - Sum height , Equal width
  4159.                                     wm = w1;
  4160.                                     hm = h1 + h2;
  4161.                                     new_micro1[0] = 0;
  4162.                                     new_micro1[1] = h2;
  4163.                                 }
  4164.                                 // Calculate micro and macro coordinates with referencial 0,0 on the top left corner
  4165.                                 new_micro2[0] = 0;
  4166.                                 new_micro2[1] = 0;
  4167.                                 new_micro2[2] = w2 - 1;
  4168.                                 new_micro2[3] = h2 - 1;
  4169.  
  4170.                                 new_micro1[2] = wm - 1;
  4171.                                 new_micro1[3] = hm - 1;
  4172.                             }
  4173.                             else if (minContIndex == 1 || minContIndex == 3)
  4174.                             {
  4175.                                 if (minContIndex == 1)
  4176.                                 {
  4177.                                     // Right Edge - Equal height , Sum width
  4178.                                     wm = w1 + w2;
  4179.                                     hm = h1;
  4180.                                     new_micro2[0] = w1;
  4181.                                     new_micro2[1] = 0;
  4182.                                 }
  4183.                                 else if (minContIndex == 3)
  4184.                                 {
  4185.                                     // Bottom Edge - Sum height , Equal width
  4186.                                     wm = w1;
  4187.                                     hm = h1 + h2;
  4188.                                     new_micro2[0] = 0;
  4189.                                     new_micro2[1] = h1;
  4190.                                 }
  4191.                                 // Calculate micro and macro coordinates with referencial 0,0 on the top left corner
  4192.                                 new_micro1[0] = 0;
  4193.                                 new_micro1[1] = 0;
  4194.                                 new_micro1[2] = w1 - 1;
  4195.                                 new_micro1[3] = h1 - 1;
  4196.  
  4197.                                 new_micro2[2] = wm - 1;
  4198.                                 new_micro2[3] = hm - 1;
  4199.                             } // End of 'Switch' minContIndex
  4200.  
  4201.                             defaultPos = DiscoverMacroCornerCoord(defaultMacroPos, old_micro1, old_micro2, microCellCombination.Item1, microCellCombination.Item2, out double cxm, out double cym);
  4202.                             Console.WriteLine("Macro Position: {0} ({1},{2})", defaultPos, cxm, cym);
  4203.  
  4204.                             // At this phase, we have chosen the corner for the new macro cell
  4205.                             // Calculate where each micro will land in the final img
  4206.                             switch (defaultPos)
  4207.                             {
  4208.                                 case 0:
  4209.                                     // Same has having 0 ref.
  4210.                                     // Do nothing
  4211.                                     macro[0] = cxm;          // Top Left X
  4212.                                     macro[1] = cym;          // Top Left Y
  4213.                                     macro[2] = cxm + (wm - 1);     // Bottom Right X
  4214.                                     macro[3] = cym + (hm - 1);     // Bottom Right Y
  4215.                                     break;
  4216.  
  4217.                                 case 1:
  4218.                                     // Move Up Left
  4219.                                     new_micro1[0] = cxm - (wm - 1) + new_micro1[0];
  4220.                                     new_micro1[1] = cym - (hm - 1) + new_micro1[1];
  4221.                                     new_micro1[2] = cxm - (wm - 1) + new_micro1[2];
  4222.                                     new_micro1[3] = cym - (hm - 1) + new_micro1[3];
  4223.  
  4224.                                     new_micro2[0] = cxm - (wm - 1) + new_micro2[0];
  4225.                                     new_micro2[1] = cym - (hm - 1) + new_micro2[1];
  4226.                                     new_micro2[2] = cxm - (wm - 1) + new_micro2[2];
  4227.                                     new_micro2[3] = cym - (hm - 1) + new_micro2[3];
  4228.  
  4229.                                     macro[0] = cxm - (wm - 1);      // Top Left X
  4230.                                     macro[1] = cym - (hm - 1);      // Top Left Y
  4231.                                     macro[2] = cxm;                 // Bottom Right X
  4232.                                     macro[3] = cym;                 // Bottom Right Y
  4233.                                     break;
  4234.  
  4235.                                 case 2:
  4236.                                     // Move Left
  4237.                                     new_micro1[0] = cxm - (wm - 1) + new_micro1[0];
  4238.                                     new_micro1[2] = cxm - (wm - 1) + new_micro1[2];
  4239.  
  4240.                                     new_micro2[0] = cxm - (wm - 1) + new_micro2[0];
  4241.                                     new_micro2[2] = cxm - (wm - 1) + new_micro2[2];
  4242.  
  4243.                                     macro[0] = cxm - (wm - 1);    // Top Left X
  4244.                                     macro[1] = cym;         // Top Left Y
  4245.                                     macro[2] = cxm;         // Bottom Right X
  4246.                                     macro[3] = cym + (hm - 1);    // Bottom Right Y
  4247.                                     break;
  4248.  
  4249.                                 case 3:
  4250.                                     // Move Up
  4251.                                     new_micro1[1] = cym - (hm - 1) + new_micro1[1];
  4252.                                     new_micro1[3] = cym - (hm - 1) + new_micro1[3];
  4253.  
  4254.                                     new_micro2[1] = cym - (hm - 1) + new_micro2[1];
  4255.                                     new_micro2[3] = cym - (hm - 1) + new_micro2[3];
  4256.  
  4257.                                     macro[0] = cxm;         // Top Left X
  4258.                                     macro[1] = cym - (hm - 1);    // Top Left Y
  4259.                                     macro[2] = cxm + (wm - 1);    // Bottom Right X
  4260.                                     macro[3] = cym;         // Bottom Right Y
  4261.                                     break;
  4262.                             } // End of Switch defaultPos
  4263.  
  4264.                             macro[4] = 0;                   // Angle
  4265.                             macro[5] = 1;                   // Positioned in ImgFinal
  4266.  
  4267.                             // Translate micros: To (image) - From (image)
  4268.                             // img      - Final
  4269.                             // imgCpy   - Original
  4270.  
  4271.                             if (old_micro1[5] == 1 || old_micro2[5] == 1)
  4272.                             {
  4273.                                 img_aux = img.Copy();
  4274.  
  4275.                                 // Clear Micros from the image
  4276.                                 if (old_micro1[5] == 1)
  4277.                                     ClearTrace(img, old_micro1, bckgrnd);                                // Remove micro1 Trace from final img
  4278.  
  4279.                                 if (old_micro2[5] == 1)
  4280.                                     ClearTrace(img, old_micro2, bckgrnd);                                // Remove micro2 Trace from final img
  4281.  
  4282.                                 if (old_micro1[5] == 1)
  4283.                                 {
  4284.                                     Console.WriteLine("Moving Micro1");
  4285.                                     Translation__xy_NoReplace(img, img_aux, old_micro1, new_micro1);
  4286.                                 }
  4287.  
  4288.                                 if (old_micro2[5] == 1)
  4289.                                 {
  4290.                                     Console.WriteLine("Moving Micro2");
  4291.                                     Translation__xy_NoReplace(img, img_aux, old_micro2, new_micro2);
  4292.                                 }
  4293.                             } // End of Micro1 || Micro 2 in ImgFinal
  4294.  
  4295.                             if (old_micro1[5] == 0)
  4296.                                 Translation_xy(img, imgCpy, old_micro1, new_micro1, bckgrnd);           // Piece 1 in imgOriginal
  4297.  
  4298.                             if (old_micro2[5] == 0)
  4299.                                 Translation_xy(img, imgCpy, old_micro2, new_micro2, bckgrnd);           // Piece 2 in imgOriginal
  4300.  
  4301.  
  4302.                             // Remove Micros
  4303.                             obj_list.Remove(microCellCombination.Item1);
  4304.                             obj_list.Remove(microCellCombination.Item2);
  4305.  
  4306.                             // Add Macro that uses micro1 label
  4307.                             obj_list.Add(microCellCombination.Item1, macro);
  4308.  
  4309.                             // Recalculate Piece Resemblance
  4310.                             EdgeRecalculation(img, imgCpy, obj_list, piece_resemblance, microCellCombination.Item1, microCellCombination);
  4311.  
  4312.                         } // End of While objList.Count > 1 for objects with equal edge sizes
  4313.  
  4314.                         // If there are still more than 1 object, proceed to Scale
  4315.                         if (obj_list.Count > 1)
  4316.                         {
  4317.                             Console.WriteLine("Scaling If | Current Obj_Count: {0}", obj_list.Count);
  4318.  
  4319.                             // Calculate Piece Resemblence
  4320.                             // For all edges, even those varying in size
  4321.                             piece_resemblance = EdgeComparison(imgCpy, img, obj_list, true);
  4322.  
  4323.                             // Find least Contrast Edge Match
  4324.                             // Init Micro-cell combination variables
  4325.                             Tuple<int, int> microCellCombination = new Tuple<int, int>(0, 0);
  4326.                             int minContrast = 255;
  4327.                             int minContIndex = 0;
  4328.  
  4329.                             // Find the smallest value of contrast -- Find mergeable micro cells
  4330.                             foreach (var edgesIterator in piece_resemblance)
  4331.                             {
  4332.                                 for (int i = 0; i < edgesIterator.Value.Length; i++)
  4333.                                 {
  4334.                                     if (edgesIterator.Value[i] < minContrast)   // Save the index (corresponds to the edge), the contrast of such edge, and the key
  4335.                                     {
  4336.                                         minContIndex = i;
  4337.                                         minContrast = edgesIterator.Value[i];
  4338.                                         microCellCombination = edgesIterator.Key;
  4339.                                     }
  4340.                                 }
  4341.                             } // End of Find Smallest Value
  4342.                             Console.WriteLine("Scaling Match Result: [{0}] {1},{2}", minContIndex, microCellCombination.Item1, microCellCombination.Item2);
  4343.  
  4344.                             // Get Micros
  4345.                             obj_list.TryGetValue(microCellCombination.Item1, out double[] old_micro1);
  4346.                             obj_list.TryGetValue(microCellCombination.Item2, out double[] old_micro2);
  4347.  
  4348.                             double[] scale_sqr, static_sqr;
  4349.                             int sum1 = 0,
  4350.                                 sum2 = 0,
  4351.                                 label_scale;
  4352.  
  4353.                             // Find what micro to scale
  4354.                             // Objects in imgFinal have priority
  4355.                             // If both pieces are in the same Img, choose based upon the sums of their resemblences
  4356.                             if (old_micro1[5] == old_micro2[5])
  4357.                             {
  4358.                                 // Choose based on Resemblence
  4359.                                 foreach (var edgesIterator in piece_resemblance)
  4360.                                 {
  4361.                                     if (edgesIterator.Key.Item1 == microCellCombination.Item1 || edgesIterator.Key.Item2 == microCellCombination.Item1)
  4362.                                     {
  4363.                                         for (int i = 0; i < edgesIterator.Value.Length; i++)
  4364.                                         {
  4365.                                             sum1 += edgesIterator.Value[i];
  4366.                                         }
  4367.                                     }
  4368.                                     else if (edgesIterator.Key.Item1 == microCellCombination.Item2 || edgesIterator.Key.Item2 == microCellCombination.Item2)
  4369.                                     {
  4370.                                         for (int i = 0; i < edgesIterator.Value.Length; i++)
  4371.                                         {
  4372.                                             sum2 += edgesIterator.Value[i];
  4373.                                         }
  4374.                                     }
  4375.                                 } // End of Sum Resemblences
  4376.                                 Console.WriteLine("Sum Result: {0},{1}", sum1, sum2);
  4377.                             } // End of Choose based on Resemblence
  4378.  
  4379.                             // Design Static and Scaleable Piece
  4380.                             if ((old_micro1[5] == 1 && old_micro2[5] == 0) || sum1 < sum2)
  4381.                             {
  4382.                                 Console.WriteLine("Scaling Micro 1 | In: {0}", old_micro1[5]);
  4383.                                 scale_sqr = old_micro1;
  4384.                                 label_scale = microCellCombination.Item1;
  4385.                                 static_sqr = old_micro2;
  4386.                             }
  4387.                             else if ((old_micro2[5] == 1 && old_micro1[5] == 0) || sum2 < sum1)
  4388.                             {
  4389.                                 Console.WriteLine("Scaling Micro 2 | In: {0}", old_micro2[5]);
  4390.                                 scale_sqr = old_micro2;
  4391.                                 label_scale = microCellCombination.Item2;
  4392.                                 static_sqr = old_micro1;
  4393.                             }
  4394.                             else
  4395.                             {
  4396.                                 Console.WriteLine("Scaling SEGMENTATION ERRROR DUMPINxsinxwsG COOooOOOrrr€€€€");
  4397.                                 scale_sqr = null;
  4398.                                 label_scale = 0;
  4399.                                 static_sqr = null;
  4400.                                 return;
  4401.                             }
  4402.  
  4403.                             // Match Scaleable Piece to match Static Piece by calculating Scaling Factor
  4404.                             double[] final_sqr;
  4405.                             double scale_w = scale_sqr[2] - scale_sqr[0] + 1,
  4406.                                 static_w = static_sqr[2] - static_sqr[0] + 1,
  4407.                                 scale_h = scale_sqr[3] - scale_sqr[1] + 1,
  4408.                                 static_h = static_sqr[3] - static_sqr[1] + 1,
  4409.                                 sF = 1;
  4410.                             if (minContIndex == 0 || minContIndex == 1)
  4411.                             {
  4412.                                 // Match Static Width
  4413.                                 if (static_w > scale_w)
  4414.                                 {
  4415.                                     // Expand
  4416.                                     sF = static_w / scale_w;
  4417.                                     Console.WriteLine("Zoom Width with sF: {0}", sF);
  4418.                                 }
  4419.                                 else
  4420.                                 {
  4421.                                     // Contract
  4422.                                     sF = scale_w / static_w;
  4423.                                     Console.WriteLine("Unzoom Width with sF: {0}", sF);
  4424.                                 }
  4425.                             }
  4426.                             else if (minContIndex == 2 || minContIndex == 3)
  4427.                             {
  4428.                                 // Match Static Height
  4429.                                 if (static_h > scale_w)
  4430.                                 {
  4431.                                     // Expand
  4432.                                     sF = static_h / scale_h;
  4433.                                     Console.WriteLine("Zoom Width with sF: {0}", sF);
  4434.                                 }
  4435.                                 else
  4436.                                 {
  4437.                                     // Contract
  4438.                                     sF = scale_h / static_h;
  4439.                                     Console.WriteLine("Unzoom Width with sF: {0}", sF);
  4440.                                 }
  4441.                             } // End of 'Switch' minContIndex
  4442.  
  4443.                             return;
  4444.  
  4445.                             // Scale Scaleable Piece
  4446.                             if (scale_sqr[5] == 1)
  4447.                             {
  4448.                                 img_aux = img.Copy();
  4449.                                 final_sqr = Scale_Piece(img, img_aux, scale_sqr, sF, bckgrnd);
  4450.                             } else
  4451.                             {
  4452.                                 img_aux = imgCpy.Copy();
  4453.                                 final_sqr = Scale_Piece(imgCpy, img_aux, scale_sqr, sF, bckgrnd);
  4454.                             }
  4455.  
  4456.                             // Update Obj_List
  4457.                             obj_list.Remove(label_scale);
  4458.                             obj_list.Add(label_scale, final_sqr);
  4459.  
  4460.                         } // End of If objList.Count > 1 for scaling purposes
  4461.                     } // End of While objList.Count > 1
  4462.                 } // End of If objList.Count > 1
  4463.  
  4464.                 Console.WriteLine("Centering | Current Obj_Count: {0}", obj_list.Count);
  4465.  
  4466.                 // Center the unified piece in the img
  4467.                 Console.WriteLine("Centering Solved Puzzle");
  4468.                 obj_list.TryGetValue(1, out double[] old_micro);
  4469.  
  4470.                 double centercornerx = (int)(Math.Round(w / 2.0) - (Math.Round((old_micro[2] + old_micro[0]) / 2) - old_micro[0]));
  4471.                 double centercornery = (int)(Math.Round(h / 2.0) - (Math.Round((old_micro[3] + old_micro[1]) / 2) - old_micro[1]));
  4472.  
  4473.                 double[] center_sqr = new double[4] { centercornerx, centercornery, centercornerx + (old_micro[2] - old_micro[0]), centercornery + (old_micro[3] - old_micro[1]) };
  4474.  
  4475.                 // Translate to new position
  4476.                 img_aux = img.Copy();
  4477.                 ClearTrace(img, old_micro, bckgrnd);
  4478.                 Translation__xy_NoReplace(img, img_aux, old_micro, center_sqr);
  4479.  
  4480.             } // End of Unsafe
  4481.         } // End of Join Pieces
  4482.  
  4483.         /// <summary>
  4484.         /// Function that solves the puzzle
  4485.         /// </summary>
  4486.         /// <param name="img">Input/Output image</param>
  4487.         /// <param name="imgCopy">Image Copy</param>
  4488.         /// <param name="Pieces_positions">List of positions (Left-x,Top-y,Right-x,Bottom-y) of all detected pieces</param>
  4489.         /// <param name="Pieces_angle">List of detected pieces' angles</param>
  4490.         /// <param name="level">Level of image</param>
  4491.         static public void puzzle(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy, out List<int[]> Pieces_positions, out List<int> Pieces_angle, int level)
  4492.         {
  4493.             Pieces_positions = new List<int[]>();
  4494.             Pieces_angle = new List<int>();
  4495.  
  4496.             Dictionary<int, double[]> obj_list;
  4497.             Dictionary<int, double[]>.Enumerator Enum;
  4498.  
  4499.             // Labeling of existing pieces
  4500.             int[,] labels = ImageClass.Classification(img, true, false);
  4501.  
  4502.             if (labels != null)
  4503.             {
  4504.                 // Get a list of existing pieces properties according to their label
  4505.                 obj_list = ImageClass.FindCorners(labels, img.Width, img.Height);
  4506.                 Console.WriteLine("Pieces Labeled");
  4507.  
  4508.                 // Rotate the pieces that require it.
  4509.                 ImageClass.RotatePieces(img, imgCopy, labels, obj_list);
  4510.  
  4511.                 // Merge all the pieces
  4512.                 Image<Bgr, byte> img_aux = img.Copy();
  4513.                 ImageClass.JoinPieces(img, img_aux, obj_list);
  4514.                 Console.WriteLine("All Pieces Merged");
  4515.  
  4516.                 img_aux.CopyTo(imgCopy); // DEBUG
  4517.  
  4518.                 // Finish - Update out parameters
  4519.                 Enum = obj_list.GetEnumerator();
  4520.  
  4521.                 int[] sqr;
  4522.                 double[] piece;
  4523.                 while (Enum.MoveNext())
  4524.                 {
  4525.                     piece = Enum.Current.Value;
  4526.                     sqr = new int[4] { (int)piece[0], (int)piece[1], (int)piece[2], (int)piece[3] };
  4527.                     Pieces_positions.Add(sqr);
  4528.                     Pieces_angle.Add((int)piece[4]);
  4529.                 }
  4530.             } // End of Label != null
  4531.         } // End of Puzzle
  4532.  
  4533.  
  4534.         // ***  Extra Functions  ***
  4535.  
  4536.         static public void Translation_NaoConseguiMudarOMetodoDeEnderecamento(Image<Bgr, byte> img, Image<Bgr, byte> imgCopy, int dx, int dy)
  4537.         {
  4538.             unsafe
  4539.             {
  4540.                 MIplImage m = imgCopy.MIplImage;
  4541.                 MIplImage d = img.MIplImage;
  4542.                 byte* dataPtr_org = (byte*)m.imageData.ToPointer(); // Pointer to the original image
  4543.                 byte* dataPtr; // Pointer to the final image
  4544.                 byte* o_px;
  4545.  
  4546.                 int width = imgCopy.Width;
  4547.                 int height = imgCopy.Height;
  4548.                 int widthStep = m.widthStep;
  4549.                 int nChan = m.nChannels; // number of channels - 3
  4550.                 int padding = widthStep - nChan * width;
  4551.  
  4552.                 int x, y;
  4553.                 int x_blk_inf = 0, x_blk_sup = 0, y_blk_inf = 0, y_blk_sup = 0;
  4554.                 int x_img_inf = 0, x_img_sup = 0, y_img_inf = 0, y_img_sup = 0;
  4555.  
  4556.                 if (dx > 0)
  4557.                 {
  4558.                     x_blk_inf = 0;
  4559.                     x_blk_sup = dx;
  4560.                     x_img_inf = dx;
  4561.                     x_img_sup = width;
  4562.                 }
  4563.                 else if (dx < 0)
  4564.                 {
  4565.                     x_img_inf = 0;
  4566.                     x_img_sup = width + dx;
  4567.                     x_blk_inf = width + dx;
  4568.                     x_blk_sup = width;
  4569.                 }
  4570.  
  4571.                 if (dy > 0)
  4572.                 {
  4573.                     y_blk_inf = 0;
  4574.                     y_blk_sup = dy;
  4575.                     y_img_inf = dy;
  4576.                     y_img_sup = height;
  4577.                 }
  4578.                 else if (dy < 0)
  4579.                 {
  4580.                     y_img_inf = 0;
  4581.                     y_img_sup = height + dy;
  4582.                     y_blk_inf = height + dy;
  4583.                     y_blk_sup = height;
  4584.                 }
  4585.  
  4586.                 if (nChan == 3) // image in RGB
  4587.                 {
  4588.                     dataPtr = (byte*)d.imageData.ToPointer() + x_blk_inf * nChan;
  4589.                     // Process dx bigger rectangle
  4590.                     for (y = 0; y < height; y++)
  4591.                     {
  4592.                         for (x = x_blk_inf; x < x_blk_sup; x++)
  4593.                         {
  4594.                             dataPtr[0] = 0;
  4595.                             dataPtr[1] = 0;
  4596.                             dataPtr[2] = 0;
  4597.  
  4598.                             dataPtr += nChan;
  4599.                         }
  4600.                         dataPtr += padding + (x_blk_sup - x_blk_inf) * nChan;
  4601.                     }
  4602.  
  4603.                     dataPtr = (byte*)d.imageData.ToPointer() + x_img_inf * nChan + y_blk_inf * widthStep;
  4604.                     // Process dy smaller rectangle
  4605.                     for (y = y_blk_inf; y < y_blk_sup; y++)
  4606.                     {
  4607.                         for (x = x_img_inf; x < x_img_sup; x++)
  4608.                         {
  4609.                             dataPtr[0] = 0;
  4610.                             dataPtr[1] = 0;
  4611.                             dataPtr[2] = 0;
  4612.  
  4613.                             dataPtr += nChan;
  4614.                         }
  4615.                         dataPtr += padding + (x_img_sup - x_img_inf) * nChan;
  4616.                     }
  4617.  
  4618.                     dataPtr = (byte*)d.imageData.ToPointer() + y_img_inf * nChan + y_img_inf * widthStep;
  4619.                     // Process image rectangle
  4620.                     for (y = y_img_inf; y < y_img_sup; y++)
  4621.                     {
  4622.                         //diff_y_ws = (y - dy) * widthStep;
  4623.                         for (x = y_img_inf; x < x_img_sup; x++)
  4624.                         {
  4625.                             o_px = (dataPtr_org + (y - dy) * widthStep + (x - dx) * nChan);
  4626.  
  4627.                             dataPtr[0] = (byte)o_px[0];
  4628.                             dataPtr[1] = (byte)o_px[1];
  4629.                             dataPtr[2] = (byte)o_px[2];
  4630.  
  4631.                             dataPtr += nChan;
  4632.                         }
  4633.                         dataPtr += padding + (x_img_sup - y_img_inf) * nChan;
  4634.                     }
  4635.                 } // End of nChan = 3
  4636.             } // End of Unsafe
  4637.         } // End of Translation
  4638.  
  4639.         // To Finish: Upper Margin || Check Dilate Flag, it is possible not right
  4640.         static public void Dilation_3x3(Image<Bgr, byte> img, Image<Bgr, byte> imgUndo, bool[,] matrix)
  4641.         {
  4642.             unsafe
  4643.             {
  4644.                 MIplImage d = img.MIplImage;
  4645.                 MIplImage m = imgUndo.MIplImage;
  4646.                 byte* dataPtr = (byte*)d.imageData.ToPointer();   // Pointer to the final image
  4647.                 byte* dataPtr_org = (byte*)m.imageData.ToPointer();   // Pointer to the final image
  4648.                 byte* px;
  4649.  
  4650.                 int w = img.Width;
  4651.                 int h = img.Height;
  4652.                 int nChan = d.nChannels;
  4653.                 int widthStep = d.widthStep;
  4654.                 int padding = widthStep - nChan * w;
  4655.                 int x, y;
  4656.  
  4657.                 if (nChan == 3)
  4658.                 {
  4659.                     dataPtr += nChan + widthStep;
  4660.                     dataPtr_org += nChan + widthStep;
  4661.                     for (y = 1; y < h - 1; y++)
  4662.                     {
  4663.                         for (x = 1; x < w - 1; x++)
  4664.                         {
  4665.                             // Kernel
  4666.                             bool dilate = false;
  4667.                             byte px_value = 0;
  4668.                             // Loop Y
  4669.                             for (int i = 0; i < 3; i++)
  4670.                             {
  4671.                                 if (dilate)
  4672.                                 {
  4673.                                     if (dataPtr[0] != px_value)
  4674.                                     {
  4675.                                         dataPtr[0] = 0;
  4676.                                         dataPtr[1] = 0;
  4677.                                         dataPtr[2] = 255;
  4678.                                     }
  4679.                                     else
  4680.                                     {
  4681.                                         dataPtr[0] = px_value;
  4682.                                         dataPtr[1] = px_value;
  4683.                                         dataPtr[2] = px_value;
  4684.                                     }
  4685.                                     break;
  4686.                                 }
  4687.                                 // Loop X
  4688.                                 for (int j = 0; j < 3; j++)
  4689.                                 {
  4690.                                     if (matrix[i, j])
  4691.                                     {
  4692.                                         // True Value in Mask
  4693.                                         px = dataPtr_org + (j - 1) * nChan + (i - 1) * widthStep;
  4694.  
  4695.                                         if (px[0] != 255 && px[1] != 255 && px[2] != 255)
  4696.                                         {
  4697.                                             dilate = true;
  4698.                                             px_value = px[0];
  4699.                                             break;
  4700.                                         }
  4701.                                     }
  4702.                                 } // End of Kernel X Loop
  4703.                             } // End of Kernel Y Loop
  4704.                             dataPtr += nChan;
  4705.                             dataPtr_org += nChan;
  4706.                         } // End of X Loop
  4707.                         dataPtr += padding + 2 * nChan;
  4708.                         dataPtr_org += padding + 2 * nChan;
  4709.                     } // End of Y Loop
  4710.                 } // End of nChan = 3
  4711.             } // End of Unsafe
  4712.         } // End of Dilation 3x3
  4713.  
  4714.         // To Finish
  4715.         private const int HnM_Bckgrd = 255;
  4716.         static public void HitnMiss_3x3(Image<Bgr, byte> img, Image<Bgr, byte> imgUndo, int[,] matrix)
  4717.         {
  4718.             unsafe
  4719.             {
  4720.                 MIplImage d = img.MIplImage;
  4721.                 MIplImage m = imgUndo.MIplImage;
  4722.                 byte* dataPtr = (byte*)d.imageData.ToPointer();   // Pointer to the final image
  4723.                 byte* dataPtr_org = (byte*)m.imageData.ToPointer();   // Pointer to the final image
  4724.                 byte* px;
  4725.  
  4726.                 int w = img.Width;
  4727.                 int h = img.Height;
  4728.                 int nChan = d.nChannels;
  4729.                 int widthStep = d.widthStep;
  4730.                 int padding = widthStep - nChan * w;
  4731.                 int x, y;
  4732.  
  4733.                 Tuple<int, int, int> corner;
  4734.                 List<Tuple<int, int, int>> corners_list = new List<Tuple<int, int, int>>();
  4735.  
  4736.                 bool break_flag;
  4737.  
  4738.                 if (nChan == 3)
  4739.                 {
  4740.                     // Core
  4741.                     dataPtr += nChan + widthStep;
  4742.                     dataPtr_org += nChan + widthStep;
  4743.                     for (y = 1; y < h - 1; y++)
  4744.                     {
  4745.                         for (x = 1; x < w - 1; x++)
  4746.                         {
  4747.  
  4748.                             // Mask Kernel with rotation
  4749.                             for (int r = 0; r < 3; r++)
  4750.                             {
  4751.  
  4752.                                 break_flag = false;
  4753.                                 for (int i = 0; i < 3; i++)
  4754.                                 {
  4755.                                     if (break_flag)
  4756.                                         break;
  4757.  
  4758.                                     for (int j = 0; j < 3; j++)
  4759.                                     {
  4760.                                         px = dataPtr_org + (j - 1) * nChan + (i - 1) * widthStep;
  4761.  
  4762.                                         if (matrix[i, j] == 0)
  4763.                                         {
  4764.                                             if (px[0] == HnM_Bckgrd && px[1] == HnM_Bckgrd && px[2] == HnM_Bckgrd)
  4765.                                                 continue;
  4766.                                             else
  4767.                                             {
  4768.                                                 break_flag = true;
  4769.                                                 break;
  4770.                                             }
  4771.                                         }
  4772.                                         else if (matrix[i, j] == 1)
  4773.                                         {
  4774.                                             if (px[0] != HnM_Bckgrd && px[1] != HnM_Bckgrd && px[2] != HnM_Bckgrd)
  4775.                                                 continue;
  4776.                                             else
  4777.                                             {
  4778.                                                 break_flag = true;
  4779.                                                 break;
  4780.                                             }
  4781.                                         }
  4782.                                     } // End of Kernel X Loop
  4783.                                 } // End of Kernel Y Loop
  4784.  
  4785.                                 if (!break_flag)
  4786.                                 {
  4787.                                     // Pixel Matches Mask, add to list
  4788.                                     corner = new Tuple<int, int, int>(r, x, y);
  4789.                                     corners_list.Add(corner);
  4790.                                 }
  4791.  
  4792.                                 // Rotate Mask for the next iteration
  4793.                                 // Rotate45d_3x3Mask(&m);
  4794.                             } // End of Mask Rotation
  4795.  
  4796.                             dataPtr += nChan;
  4797.                             dataPtr_org += nChan;
  4798.                         } // End of X Loop
  4799.                         dataPtr += padding + 2 * nChan;
  4800.                         dataPtr_org += padding + 2 * nChan;
  4801.                     } // End of Y Loop
  4802.                 } // End of nChan = 3
  4803.             } // End of Unsafe
  4804.         } // End of Hit n Miss
  4805.  
  4806.     } // End of ImageClass
  4807. } // End of NameSpace OpenCV
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement