2017-01-05 48 views
0

我從我的WinForms項目,我發佈前一陣子工作卷積功能:
C# Convolution filter for any size matrix (1x1, 3x3, 5x5, ...) not fully applied
現在我需要變換分析這個功能,而無需使用System.Drawing.Imaging這在Xamarin中不可用。
爲此,我需要使用其他類似Android.Graphics的庫,它們沒有BitmapData結構。
我接近完成我的轉換,但我搞砸了 - 我的應用程序在計算功能時終止。
這裏是我的轉換後的代碼:Xamarin:轉換.NET卷積函數C#的Android

using System; 
using Dicom.Imaging; 
using System.Runtime.InteropServices; 
using Android.Graphics; 
using Java.Nio; 

public static Bitmap ConvolutionFunction(Bitmap bitmap, ConvMatrix m) 
    { 
     if (0 == m.Factor) 
      return bitmap; 

     int size = bitmap.Width * bitmap.Height * 4; 

     var mutableBitmap = Bitmap.CreateBitmap(bitmap.Width, bitmap.Height, bitmap.GetConfig()); 

     ByteBuffer buf = ByteBuffer.Allocate(size); 
     ByteBuffer bufSrc = ByteBuffer.Allocate(size); 

     bitmap.CopyPixelsToBuffer(buf); 
     byte[] byt = new byte[buf.Remaining()]; 
     buf.Get(byt); 

     bitmap.CopyPixelsToBuffer(bufSrc); 
     byte[] bytSrc = new byte[bufSrc.Remaining()]; 
     buf.Get(bytSrc); 

     int stride = bitmap.Width; 

     System.IntPtr Scan0 = Marshal.AllocHGlobal(byt.Length); 
     Marshal.Copy(byt, 0, Scan0, byt.Length); 

     System.IntPtr SrcScan0 = Marshal.AllocHGlobal(bytSrc.Length); 
     Marshal.Copy(bytSrc, 0, Scan0, byt.Length); 

     unsafe 
     { 
      byte* p = (byte*)(void*)Scan0; 
      byte* pSrc = (byte*)(void*)SrcScan0; 
      int nOffset = stride - bitmap.Width * m.Size; 
      int nWidth = bitmap.Width - (m.Size - 1); 
      int nHeight = bitmap.Height - (m.Size - 1); 

      int nPixel = 0; 

      for (int y = 0; y < nHeight; y++) 
      { 
       for (int x = 0; x < nWidth; x++) 
       { 
        for (int r = 0; r < m.Size; r++) 
        { 
         nPixel = 0; 
         for (int i = 0; i < m.Size; i++) 
          for (int j = 0; j < m.Size; j++) 
          { 
           nPixel += (pSrc[(m.Size * (i + 1)) - 1 - r + stride * j] * m.Arr[j, i]); 
          } 

         nPixel /= m.Factor; 
         nPixel += m.Offset; 

         if (nPixel < 0) nPixel = 0; 
         if (nPixel > 255) nPixel = 255; 
         p[(m.Size * (m.Size/2 + 1)) - 1 - r + stride * (m.Size/2)] = (byte)nPixel; 
        } 
        p += m.Size; 
        pSrc += m.Size; 
       } 

       p += nOffset; 
       pSrc += nOffset; 
      } 
     } 

     ByteBuffer retBuf = ByteBuffer.Wrap(byt); 
     mutableBitmap.CopyPixelsFromBuffer(retBuf); 

     Marshal.FreeHGlobal(Scan0); 
     Marshal.FreeHGlobal(SrcScan0); 

     return mutableBitmap; 
    } 
} 

我沒有改變不安全{..}節裏面什麼。我可能已經搞砸了一些IntPtr和步伐。
請幫助

+0

嘗試添加try-catch塊,它應該幫助你理解爲什麼你的應用程序終止。 –

+0

如果你沒有得到任何例外。你可以通過這種方式查看Xamarin日誌,例如Visual Studio> Help> Xamarin> Open logs'。 –

回答

0

過了一會兒,我發現,在Xamarin的Android實現非常快的卷積函數,這裏是結果:

public static Bitmap GaussianFilter(Bitmap image) 
    { 
     float[] conv_matrix = 
     { 1.0f/8.0f, 1.0f/4.0f, 1.0f/8.0f, 
      1.0f/4.0f, 1.0f/2.0f, 1.0f/4.0f, 
      1.0f/8.0f, 1.0f/4.0f, 1.0f/8.0f }; 

     return createBitmap_convolve(image, conv_matrix); 
    } 

    public static Bitmap createBitmap_convolve(Bitmap src, float[] coefficients) 
    { 
     //Fast method using android solution: ScriptIntrinsicConvolve3x3() 
     Bitmap result = Bitmap.CreateBitmap(src.Width, 
      src.Height, src.GetConfig()); 

     RenderScript renderScript = RenderScript.Create(Android.App.Application.Context); 

     Allocation input = Allocation.CreateFromBitmap(renderScript, src); 
     Allocation output = Allocation.CreateFromBitmap(renderScript, result); 

     ScriptIntrinsicConvolve3x3 convolution = ScriptIntrinsicConvolve3x3 
      .Create(renderScript, Element.U8_4(renderScript)); 
     convolution.SetInput(input); 
     convolution.SetCoefficients(coefficients); 
     convolution.ForEach(output); 

     output.CopyTo(result); 
     renderScript.Destroy(); 

     return result; 
    } 

這裏是Xamarin iOS的解決辦法,如果有人需要它:

using CoreImage; 
    using UIKit; 
    using CoreGraphics; 

    public static UIImage GaussianFilter(UIImage image) 
    { 
     CIImage ciImage = new CIImage(image); 
     //ciImage.CreateByApplyingGaussianBlur(2); 

     var gaussianFilter = new CIGaussianBlur() { Image = ciImage, Radius = 0.8f}; 
     CIImage output = gaussianFilter.OutputImage; 
     var context = CIContext.FromOptions(null); 
     var cgimage = context.CreateCGImage(output, output.Extent); 
     var uiImage = UIImage.FromImage(cgimage); 

     return uiImage; 
    }