2013-10-27 50 views
0

我需要建議如何加快CCL算法的第二階段。第一階段只需要幾毫秒,但第二階段需要幾秒鐘。我多次嘗試優化等價表或使用指針表,但第二遍總是非常慢。感謝您的任何建議如何加快連接組件標籤(第二階段)

 Bitmap bmp = null; 

     unsafe 
     { 
      int stride = _alg.MIplImage.widthStep; 
      byte* ptr = (byte*)_alg.MIplImage.imageData; 
      byte[] prevRow = new byte[_alg.Cols]; 

      //First pass 
      for (int i = 1; i < _alg.Rows; i++) 
      { 
       for (int j = 1; j < _alg.Cols; j++) 
       { 
        //White pixels only 
        if ((byte)ptr[j] == 255) 
        { 
         //8-connected 
         byte[] array = new byte[4] { ptr[j - 1], prevRow[j - 1], prevRow[j], prevRow[j + 1] }; 
         //New Label 
         if (array.All(x => x == 0)) 
         { 
          ptr[j] = _color; 
          prevRow[j] = ptr[j]; 
          _color++; 
          continue; 
         } 

         byte max = array.Max(); 
         byte min = array.Where(f => f > 0).Min(); 

         //color dispute 
         if (max != min) 
         { 
          ptr[j] = min; 

          if (_prevMax != max) 
          { 
           _fromToD.Add(max, min); //Add to equvalence table 
           _prevMax = max; 
          } 

         } 
         else if (max == min) //Same color 
         { 
          ptr[j] = min; 
         } 
        } 

        prevRow[j] = ptr[j]; //Aktualize previous row 

       } 

       ptr += stride; 
      } 

      //To this section, about 16 ms 
      //second pass 

      //byte* p = (byte*)(void*)bmData.Scan0.ToPointer(); 
      //int stopAddress = (int)p + bmData.Stride * bmData.Height; 

      //while ((int)p != stopAddress) 
      //{ 
      // foreach (KeyValuePair<byte, byte> pair in _fromToD) 
      // { 
      //  if (p[0] == pair.Key) 
      //  { 
      //   p[0] = pair.Value; 
      //  } 
      // } 
      // p++; 
      //} 

      //bmp.UnlockBits(bmData); 
      //About 3 sec 

回答

0

從另一端指針終於幫助。該算法已經以毫秒爲單位,而不是秒。這不是最快的實施,但也許它有助於某人。

private unsafe Bitmap ApplyAlgoritmPointer() 
    { 
     _alg._Erode(1);  //EmguCV Image.Erode 
     _alg._Dilate(3); 

     Bitmap b = _alg.Bitmap; 
     BitmapData bData = b.LockBits(new Rectangle(0, 0, _alg.Width, _alg.Height), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed); 

     byte* scan0 = (byte*)bData.Scan0.ToPointer(); 

     for (int i = 1; i < bData.Height - 1; i++) 
     { 
      for (int j = 1; j < bData.Width - 1; j++) 
      { 
       byte* dataCurrent = scan0 + i * bData.Stride + j; 

       //White pixels only 
       if (dataCurrent[0] == 255) 
       { 
        byte* dataLeft = scan0 + i * bData.Stride + (j - 1); 
        byte* dataTopLeft = scan0 + (i - 1) * bData.Stride + (j - 1); 
        byte* dataTop = scan0 + (i - 1) * bData.Stride + j; 
        byte* dataTopRight = scan0 + (i - 1) * bData.Stride + (j + 1); 

        //New label 
        if (dataLeft[0] == 0 && dataTopRight[0] == 0 && dataTopLeft[0] == 0 && dataTop[0] == 0) 
        { 
         dataCurrent[0] = _color; 
         _pixels.Add(new pixel(dataCurrent, _color)); 
         _color++; 
        } 
        else 
        { 
         byte*[] array = new byte*[4] { dataLeft, dataTopLeft, dataTop, dataTopRight }; 
         byte* max = array.MaxP(); 
         byte* min = array.MinP(); 

         if (max != min) //Differend colors 
         { 
          dataCurrent[0] = min[0];         //menim obsah adresy 

          if (!_fromToD.ContainsKey(max[0])) 
          { 
           if (max[0] == 255) continue; 

           _fromToD.Add(max[0], new List<byte>() { min[0] }); 
          } 
          else 
          { 
           if (!_fromToD[max[0]].Contains(min[0])) 
           { 
            _fromToD[max[0]].Add(min[0]); 
           } 
          } 

          _pixels.Add(new pixel(dataCurrent, min[0])); 
         } 
         else if (max == min) //Same color 
         { 
          dataCurrent[0] = min[0]; 
          _pixels.Add(new pixel(dataCurrent, min[0])); 
         } 
        } 

       } 
      } 
     } 

     //Second Pass 
     NewList(); 

     for (int k = 0; k < _pixels.Count; k++) 
     { 
      for (int l = 0; l < _fromTo.Count; l++) 
      { 
       if (_pixels[k].color == _fromTo[l].from) 
       { 
        _pixels[k].pix[0] = _fromTo[l].to; 
       } 
       else continue; 
      } 
     } 

     b.UnlockBits(bData); 

     return b; 

    } 

表等價還原

private void NewList() 
    { 
     foreach (var key in _fromToD.Reverse()) 
     { 
      _fromTo.Add(new pass(key.Key, GetByteRecursive(key.Key))); 
     } 
    } 

    private byte GetByteRecursive(byte p) 
    { 
     byte next = p; 

     if (_fromToD.ContainsKey(p)) 
     { 
      next = _fromToD[p].Last(); 
      return GetByteRecursive(next); 
     } 
     else 
     { 
      return next; 
     } 
    } 

    class pass 
    { 
     public byte from; 
     public byte to; 

     public pass(byte from, byte to) 
     { 
      this.from = from; 
      this.to = to; 
     } 
    } 

    unsafe class pixel 
    { 
     public byte* pix; 
     public byte color; 

     public pixel(byte* pixel, byte color) 
     { 
      this.pix = pixel; 
      this.color = color; 
     } 
    } 

result