VBNet.Su - Visual Basic .NET. ASP .NET. Framework .NET.
Список форумов
Графика/GDI+

О том, чего в GDI+ .NET!

Быстрый переход:
Графика/GDI+ / Visual Basic .NET (Framework x.x) (ссылка)28 января 2009 / 02:24
Ігор
Наш человек
ку 47.181654625+

вопросов: 8
советов: 9
ответов: 14
комментариев: 45


GDI+ не может преобразовывать графическую информацию в форматы 1, 4, 8, 16 бит на никсель (точнее до весии 2.0 немогла преобразовать в формат 16bppRgb565, и по сей день не справилась с форматом 16bppArgb1555). Работать нужно непосредственно с данными.

И выбора, чесно говоря особого net в сети. Смастерил свою библиотеку. Желающие могут взять на моем сайте вместе с исходным кодом на vb2008 (http://igorr.110mb.com/dll_colorquantizer.html). Однако поскольку я украиноязычный, откомментирован код на украинском. Ну, я думаю при желании можна справиться. smile

Либо кто нибудь уже сталкивался с этим делом и сам может поделиться накопленым опытом?
Комментарий #1 (ссылка)31 января 2009 / 03:08
Ігор
Наш человек
ку 47.181654625+

вопросов: 8
советов: 9
ответов: 14
комментариев: 45


Нашел хороший алгоритм квантования (быстрее работает), но на Java. Хотя, не впервой как говорится. smile

  1. /* NeuQuant Neural-Net Quantization Algorithm
  2.  * ------------------------------------------
  3.  *
  4.  * Copyright (c) 1994 Anthony Dekker
  5.  *
  6.  * NEUQUANT Neural-Net quantization algorithm by Anthony Dekker, 1994.
  7.  * See "Kohonen neural networks for optimal colour quantization"
  8.  * in "Network: Computation in Neural Systems" Vol. 5 (1994) pp 351-367.
  9.  * for a discussion of the algorithm.
  10.  * See also  <noindex><a href="http://www.acm.org/~dekker/NEUQUANT.HTML" target="_blank" rel="external nofollow">http://www.acm.org/~dekker/NEUQUANT.HTML</a></noindex>
  11.  *
  12.  * Any party obtaining a copy of these files from the author, directly or
  13.  * indirectly, is granted, free of charge, a full and unrestricted irrevocable,
  14.  * world-wide, paid up, royalty-free, nonexclusive right and license to deal
  15.  * in this software and documentation files (the "Software"), including without
  16.  * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
  17.  * and/or sell copies of the Software, and to permit persons who receive
  18.  * copies from any such party to do so, with the only requirement being
  19.  * that this copyright notice remain intact.
  20.  */
  21.  
  22.  // Adapted for Processing by Mario Klingemann
  23.  // <noindex><a href="http://www.incubator.quasimondo.com" target="_blank" rel="external nofollow">http://www.incubator.quasimondo.com</a></noindex>
  24.  
  25.  
  26. BImage pic;
  27. NeuQuant nq;
  28.  
  29. void setup(){
  30.   noStroke();
  31.   pic=loadImage("jesus.jpg");
  32.   size(pic.width,pic.height);
  33.  
  34. }
  35.  
  36. void loop(){
  37.  int colorCount=max(2,mouseX/4);
  38.   image(pic,0,0);
  39.   nq=new NeuQuant(colorCount,false);
  40.   nq.init();
  41.  
  42.   for (int i=0;i<pixels.length;i++){
  43.     pixels<em>=nq.convert(pixels<em>);
  44.   }
  45.  
  46.   int[] map=nq.getColorMap();
  47.   int sz=width/map.length;
  48.   for (int i=0;i<map.length;i++){
  49.     fill(map<em>);
  50.     rect(i*sz,height-16,(i+1)*sz,height);
  51.   }
  52. }
  53.  
  54.  
  55.  
  56. // Constructors:
  57. //    public NeuQuant (Image im, ImageObserver obs) throws IOException -- default sample = 1
  58. //    public NeuQuant (int sample, Image im, ImageObserver obs) throws IOException
  59. //    public NeuQuant (Image im, int w, int h) throws IOException -- default sample = 1
  60. //    public NeuQuant (int sample, Image im, int w, int h) throws IOException
  61.  
  62. // Initialisation method: call this first
  63. //    public void init ()
  64.  
  65. // Methods to look up pixels (use in a loop)
  66. //    public int convert (int pixel)
  67. //    public int lookup (int pixel)
  68. //    public int lookup (Color c)
  69. //    public int lookup (boolean rgb, int x, int g, int y)
  70.  
  71.  
  72. // Other methods to interrogate colour map
  73. //    public int getColorCount ()
  74. //    public Color getColor (int i)
  75.  
  76.  
  77.  
  78.  
  79.  class NeuQuant {
  80.    
  81.    int ncycles  = 128;               // no. of learning cycles
  82.  
  83.    int netsize;  // number of colours used
  84.    int specials;        // number of reserved colours used
  85.    int cutnetsize;
  86.    int maxnetpos;
  87.  
  88.    int initrad;   // for 256 cols, radius starts at 32
  89.    int radiusbiasshift = 6;
  90.    int radiusbias = 1 << radiusbiasshift;
  91.    int initBiasRadius;
  92.    int radiusdec = 30; // factor of 1/30 each cycle
  93.  
  94.    int alphabiasshift = 10;               // alpha starts at 1
  95.    int initalpha      = 1<<alphabiasshift; // biased by 10 bits
  96.  
  97.    double gamma = 1024.0;
  98.    double beta = 1.0/1024.0;
  99.    double betagamma = beta * gamma;
  100.    
  101.    double [] [] network; // the network itself
  102.    int [] [] colormap; // the network itself
  103.    
  104.    int [] netindex = new int [256]; // for network lookup - really 256
  105.    
  106.    double [] bias;  // bias and freq arrays for learning
  107.    double [] freq;
  108.  
  109.     // four primes near 500 - assume no image has a length so large
  110.     // that it is divisible by all four primes
  111.    
  112.     int prime1  = 499;
  113.    int prime2   =  491;
  114.    int prime3   =  487;
  115.    int prime4   =  503;
  116.    int maxprime=        prime4;
  117.    
  118.    int samplefac;
  119.  
  120.    NeuQuant (int colorCount,boolean blackWhite) {
  121.         samplefac = 1;
  122.        
  123.         netsize  = colorCount;    // number of colours used
  124.         if (blackWhite)
  125.             specials  = 2;            // number of reserved colours used
  126.         else
  127.             specials  = 0;            // number of reserved colours used
  128.         cutnetsize  = netsize - specials;
  129.         maxnetpos  = netsize-1;
  130.  
  131.         initrad  = netsize/8;   // for 256 cols, radius starts at 32
  132.    
  133.         initBiasRadius = initrad*radiusbias;
  134.        
  135.          network = new double [netsize] [3]; // the network itself
  136.          colormap = new int [netsize] [4]; // the network itself
  137.          bias = new double [netsize];  // bias and freq arrays for learning
  138.          freq = new double [netsize];
  139.    
  140.         setUpArrays ();
  141.     }
  142.  
  143.      
  144.      int getColorCount () {
  145.         return netsize;
  146.     }
  147.  
  148.     int[] getColorMap (){
  149.       int[] exportMap=new int[netsize];
  150.       for (int i=0;i<netsize;i++){
  151.         exportMap<em>=0xff000000 | colormap<em>[2]<<16 | colormap<em>[1]<<8 | colormap<em>[0];
  152.       }
  153.         return exportMap;
  154.     }
  155.  
  156.      void setUpArrays () {
  157.         network [0] [0] = 0.0;      // black
  158.         network [0] [1] = 0.0;
  159.         network [0] [2] = 0.0;
  160.         freq [0] = 1.0 / netsize;
  161.         bias [0] = 0.0;
  162.        
  163.         network [1] [0] = 1.0;      // white
  164.         network [1] [1] = 1.0;
  165.         network [1] [2] = 1.0;
  166.         freq [1] = 1.0 / netsize;
  167.         bias [1] = 0.0;
  168.  
  169.                                 // background
  170.         //freq [2] = 1.0 / netsize;
  171.         //bias [2] = 0.0;
  172.        
  173.         for (int i=specials; i<netsize; i++) {
  174.                     double [] p = network <em>;
  175.                     p[0] = (256.0 * (i-specials)) / cutnetsize;
  176.                     p[1] = (256.0 * (i-specials)) / cutnetsize;
  177.                     p[2] = (256.0 * (i-specials)) / cutnetsize;
  178.  
  179.                     freq<em> = 1.0 / netsize;
  180.                     bias<em> = 0.0;
  181.         }
  182.     }           
  183.  
  184.        
  185.    
  186.    
  187.  
  188.      void init () {
  189.         learn ();
  190.         fix ();
  191.         inxbuild ();
  192.     }
  193.  
  194.      void altersingle(double alpha, int i, double b, double g, double r) {
  195.         // Move neuron i towards biased (b,g,r) by factor alpha
  196.         double [] n = network<em>;                        // alter hit neuron
  197.         n[0] -= (alpha*(n[0] - b));
  198.         n[1] -= (alpha*(n[1] - g));
  199.         n[2] -= (alpha*(n[2] - r));
  200.     }
  201.  
  202.      void alterneigh(double alpha, int rad, int i, double b, double g, double r) {
  203.        
  204.         int lo = i-rad;   if (lo<specials-1) lo=specials-1;
  205.         int hi = i+rad;   if (hi>netsize) hi=netsize;
  206.  
  207.         int j = i+1;
  208.         int k = i-1;
  209.         int q = 0;
  210.         while ((j<hi) || (k>lo)) {
  211.             double a = (alpha * (rad*rad - q*q)) / (rad*rad);
  212.             q ++;
  213.             if (j<hi) {
  214.                 double [] p = network[j];
  215.                 p[0] -= (a*(p[0] - b));
  216.                 p[1] -= (a*(p[1] - g));
  217.                 p[2] -= (a*(p[2] - r));
  218.                 j++;
  219.             }
  220.             if (k>lo) {
  221.                 double [] p = network[k];
  222.                 p[0] -= (a*(p[0] - b));
  223.                 p[1] -= (a*(p[1] - g));
  224.                 p[2] -= (a*(p[2] - r));
  225.                 k--;
  226.             }
  227.         }
  228.     }
  229.    
  230.      int contest (double b, double g, double r) {    // Search for biased BGR values
  231.         // finds closest neuron (min dist) and updates freq
  232.         // finds best neuron (min dist-bias) and returns position
  233.         // for frequently chosen neurons, freq<em> is high and bias<em> is negative
  234.         // bias<em> = gamma*((1/netsize)-freq<em>)
  235.  
  236.         double bestd = Float.MAX_VALUE;
  237.         double bestbiasd = bestd;
  238.         int bestpos = -1;
  239.         int bestbiaspos = bestpos;
  240.        
  241.         for (int i=0; i<netsize; i++) {
  242.             double [] n = network<em>;
  243.             double dist = n[0] - b;   if (dist<0) dist = -dist;
  244.             double a = n[1] - g;   if (a<0) a = -a;
  245.             dist += a;
  246.             a = n[2] - r;   if (a<0) a = -a;
  247.             dist += a;
  248.             if (dist<bestd) {bestd=dist; bestpos=i;}
  249.             double biasdist = dist - bias <em>;
  250.             if (biasdist<bestbiasd) {bestbiasd=biasdist; bestbiaspos=i;}
  251.             freq <em> -= beta * freq <em>;
  252.             bias <em> += betagamma * freq <em>;
  253.         }
  254.         freq[bestpos] += beta;
  255.         bias[bestpos] -= betagamma;
  256.         return bestbiaspos;
  257.     }
  258.    
  259.      int specialFind (double b, double g, double r) {
  260.         for (int i=0; i<specials; i++) {
  261.             double [] n = network<em>;
  262.             if (n[0] == b && n[1] == g && n[2] == r) return i;
  263.         }
  264.         return -1;
  265.     }
  266.    
  267.      void learn() {
  268.         int biasRadius = initBiasRadius;
  269.         int alphadec = 30 + ((samplefac-1)/3);
  270.         int lengthcount = pixels.length;
  271.         int samplepixels = lengthcount / samplefac;
  272.         int delta = samplepixels / ncycles;
  273.         int alpha = initalpha;
  274.  
  275.             int i = 0;
  276.         int rad = biasRadius >> radiusbiasshift;
  277.         if (rad <= 1) rad = 0;
  278.        
  279.         //System.err.println("beginning 1D learning: samplepixels=" + samplepixels + "  rad=" + rad);
  280.  
  281.         int step = 0;
  282.         int pos = 0;
  283.        
  284.         if ((lengthcount%prime1) != 0) step = prime1;
  285.         else {
  286.             if ((lengthcount%prime2) !=0) step = prime2;
  287.             else {
  288.                 if ((lengthcount%prime3) !=0) step = prime3;
  289.                 else step = prime4;
  290.             }
  291.         }
  292.        
  293.         i = 0;
  294.         while (i < samplepixels) {
  295.             int p = pixels [pos];
  296.                 int red   = (p >> 16) & 0xff;
  297.                 int green = (p >>  8) & 0xff;
  298.                 int blue  = (p      ) & 0xff;
  299.  
  300.             double b = blue;
  301.             double g = green;
  302.             double r = red;
  303.  
  304.                 /*
  305.             if (i == 0) {   // remember background colour
  306.                 network [2] [0] = b;
  307.                 network [2] [1] = g;
  308.                 network [2] [2] = r;
  309.             }
  310. */
  311.             int j = specialFind (b, g, r);
  312.             j = j < 0 ? contest (b, g, r) : j;
  313.  
  314.                         if (j >= specials) {   // don't learn for specials
  315.                 double a = (1.0 * alpha) / initalpha;
  316.                 altersingle (a, j, b, g, r);
  317.                 if (rad > 0) alterneigh (a, rad, j, b, g, r);   // alter neighbours
  318.             }
  319.  
  320.             pos += step;
  321.             while (pos >= lengthcount) pos -= lengthcount;
  322.                 
  323.             i++;
  324.             if (i%delta == 0) { 
  325.                 alpha -= alpha / alphadec;
  326.                 biasRadius -= biasRadius / radiusdec;
  327.                 rad = biasRadius >> radiusbiasshift;
  328.                 if (rad <= 1) rad = 0;
  329.             }
  330.         }
  331.         //System.err.println("finished 1D learning: final alpha=" + (1.0 * alpha)/initalpha + "!");
  332.     }
  333.  
  334.      void fix() {
  335.         for (int i=0; i<netsize; i++) {
  336.             for (int j=0; j<3; j++) {
  337.                 int x = (int) (0.5 + network<em>[j]);
  338.                 if (x < 0) x = 0;
  339.                 if (x > 255) x = 255;
  340.                 colormap<em>[j] = x;
  341.             }
  342.             colormap<em>[3] = i;
  343.         }
  344.     }
  345.  
  346.      void inxbuild() {
  347.         // Insertion sort of network and building of netindex[0..255]
  348.  
  349.         int previouscol = 0;
  350.         int startpos = 0;
  351.  
  352.         for (int i=0; i<netsize; i++) {
  353.             int[] p = colormap<em>;
  354.             int[] q = null;
  355.             int smallpos = i;
  356.             int smallval = p[1];                        // index on g
  357.             // find smallest in i..netsize-1
  358.             for (int j=i+1; j<netsize; j++) {
  359.                 q = colormap[j];
  360.                 if (q[1] < smallval) {            // index on g
  361.                     smallpos = j;
  362.                     smallval = q[1];    // index on g
  363.                 }
  364.             }
  365.             q = colormap[smallpos];
  366.             // swap p (i) and q (smallpos) entries
  367.             if (i != smallpos) {
  368.                 int j = q[0];   q[0] = p[0];   p[0] = j;
  369.                 j = q[1];   q[1] = p[1];   p[1] = j;
  370.                 j = q[2];   q[2] = p[2];   p[2] = j;
  371.                 j = q[3];   q[3] = p[3];   p[3] = j;
  372.             }
  373.             // smallval entry is now in position i
  374.             if (smallval != previouscol) {
  375.                 netindex[previouscol] = (startpos+i)>>1;
  376.                 for (int j=previouscol+1; j<smallval; j++) netindex[j] = i;
  377.                 previouscol = smallval;
  378.                 startpos = i;
  379.             }
  380.         }
  381.         netindex[previouscol] = (startpos+maxnetpos)>>1;
  382.         for (int j=previouscol+1; j<256; j++) netindex[j] = maxnetpos; // really 256
  383.     }
  384.  
  385.      int convert (int pixel) {
  386.         int alfa = (pixel >> 24) & 0xff;
  387.             int r   = (pixel >> 16) & 0xff;
  388.             int g = (pixel >>  8) & 0xff;
  389.             int b  = (pixel      ) & 0xff;
  390.             int i = inxsearch(b, g, r);
  391.             int bb = colormap<em>[0];
  392.             int gg = colormap<em>[1];
  393.             int rr = colormap<em>[2];
  394.             return (alfa << 24) | (rr << 16) | (gg << 8) | (bb);
  395.     }
  396.  
  397.     int lookup (int pixel) {
  398.             int r   = (pixel >> 16) & 0xff;
  399.             int g = (pixel >>  8) & 0xff;
  400.             int b  = (pixel      ) & 0xff;
  401.             int i = inxsearch(b, g, r);
  402.             return i;
  403.     }
  404.  
  405.     int lookup (boolean rgb, int x, int g, int y) {
  406.             int i = rgb ? inxsearch (y, g, x) : inxsearch (x, g, y);
  407.             return i;
  408.     }
  409.  
  410.        
  411.      int inxsearch(int b, int g, int r) {
  412.         // Search for BGR values 0..255 and return colour index
  413.         int bestd = 1000;      // biggest possible dist is 256*3
  414.         int best = -1;
  415.         int i = netindex[g];        // index on g
  416.         int j = i-1;                // start at netindex[g] and work outwards
  417.  
  418.         while ((i<netsize) || (j>=0)) {
  419.             if (i<netsize) {
  420.                 int [] p = colormap<em>;
  421.                 int dist = p[1] - g;                // inx key
  422.                 if (dist >= bestd) i = netsize;     // stop iter
  423.                 else {
  424.                     if (dist<0) dist = -dist;
  425.                     int a = p[0] - b;   if (a<0) a = -a;
  426.                     dist += a;
  427.                     if (dist<bestd) {
  428.                         a = p[2] - r;   if (a<0) a = -a;
  429.                         dist += a;
  430.                         if (dist<bestd) {bestd=dist; best=i;}
  431.                     }
  432.                     i++;
  433.                 }
  434.             }
  435.             if (j>=0) {
  436.                 int [] p = colormap[j];
  437.                 int dist = g - p[1]; // inx key - reverse dif
  438.                 if (dist >= bestd) j = -1; // stop iter
  439.                 else {
  440.                     if (dist<0) dist = -dist;
  441.                     int a = p[0] - b;   if (a<0) a = -a;
  442.                     dist += a;
  443.                     if (dist<bestd) {
  444.                         a = p[2] - r;   if (a<0) a = -a;
  445.                         dist += a;
  446.                         if (dist<bestd) {bestd=dist; best=j;}
  447.                     }
  448.                     j--;
  449.                 }
  450.             }
  451.         }
  452.  
  453.         return best;
  454.     }
  455.  
  456. }
Страницы:    < назад    ·    вперед >
1
Зарегистрируйтесь, чтобы иметь возможность участвовать в жизни форума.