Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将Xamarin.android与OpenCV集成_Opencv_Xamarin.android - Fatal编程技术网

如何将Xamarin.android与OpenCV集成

如何将Xamarin.android与OpenCV集成,opencv,xamarin.android,Opencv,Xamarin.android,我正在尝试将Xamarin.android与visual Studio中的OpenCV连接。文档非常差。有人能为我提供一些步骤吗?在Xamarin.android上使用OpenCV的方法不止一种: 1使用OpenCV4Android的绑定:OpenCV4Android是使用JNI的OpenCV(C++)for Android(Java)的包装器。通过绑定,我们在Java和C#之间有了一个接口(更多信息见) 它是在中实现的,在那里使用的是OpenCV 3.1.0。 您可以按照安装说明和“减小.dl

我正在尝试将Xamarin.android与visual Studio中的OpenCV连接。文档非常差。有人能为我提供一些步骤吗?

在Xamarin.android上使用OpenCV的方法不止一种:

1使用OpenCV4Android的绑定:OpenCV4Android是使用JNI的OpenCV(C++)for Android(Java)的包装器。通过绑定,我们在Java和C#之间有了一个接口(更多信息见)

它是在中实现的,在那里使用的是OpenCV 3.1.0。 您可以按照安装说明和“减小.dll大小”生成dll并引用它,也可以在Visual Studio解决方案中插入文件夹“/src/OpenCV.Binding”的Visual Studio项目,并将项目引用添加到此新项目

如果您想使用较新版本,可以下载较新版本的OpenCV4Android(opencv SourceForge中名为opencv-version-android-sdk.zip的文件,例如:链接上的OpenCV4Android 4.1.0),并将上一个项目中的文件夹“/src/opencv.Binding/Jars”的内容替换为文件夹“/sdk/native/libs”和提取的OpenCV4Android的“/sdk/native/3rdparty/libs”

这个项目还有一个关键点:它可以简化安装和使用,但我没有使用它,所以我不能说它是否有效

由于此方法是OpenCV4Android的绑定,而不是纯OpenCV,您将使用OpenCV4Android()的文档。同样值得一提的是,这样我们有三层编程语言(C#-Java-C++),因此方法调用会导致性能损失(JNI是一个负担).因此,建议您尽量少打电话

<强> 2 < /St>>使用OpenCV C++的包装器:用这种方法,我们将使用C++共享库(.so),并调用它的方法(C)()。 要做到这一点,我们需要编写OpenCV方法的PInvoke,它有很多,这意味着要花很多时间。因此,我们将使用已有的方法

我们有OpenCvSharp,它是OpenCV到.NET的包装,显然工作得很好。问题:它与ARM不兼容,所以不能在智能手机上运行。 然而,一个好的灵魂使它适合在ARM设备上运行:

如何快速使用:在解决方案中插入文件夹“/src/OpenCvSharp”的项目并引用它。将“/src/OpenCvSharp.Android/Native”的内容复制到项目的文件夹“lib”或“libs”。然后将“.so”文件配置为“始终复制”到输出目录,并将其构建操作配置为“AndroidNativeLibrary”(如果您的项目是应用程序)或“嵌入式本机库”(如果您的项目是Android库)

另一种方法是安装NuGet(),这会稍微容易一些,但也需要将“.so”文件复制到“lib”或“libs”并进行配置

这个包装器使用OpenCV 3.2.0。我正在研究一种在这个项目上更新OpenCV版本的方法,但是现在,它可以工作了

这种方法的最大优点是性能(在比较两种实现时,我的应用程序提高了约30%),但一个缺点是没有现成的Android.Bitmap-OpenCV.Mat转换方法。我通过调整OpenCV4Android的转换方法实现了它们:

// Method adapted from the original OpenCV convert at https://github.com/opencv/opencv/blob/b39cd06249213220e802bb64260727711d9fc98c/modules/java/generator/src/cpp/utils.cpp
///<summary>
///This function converts an image in the OpenCV Mat representation to the Android Bitmap.
///The input Mat object has to be of the types 'CV_8UC1' (gray-scale), 'CV_8UC3' (RGB) or 'CV_8UC4' (RGBA).
///The output Bitmap object has to be of the same size as the input Mat and of the types 'ARGB_8888' or 'RGB_565'.
///This function throws an exception if the conversion fails.
///</summary>
///<param name="srcImage">srcImage is a valid input Mat object of types 'CV_8UC1', 'CV_8UC3' or 'CV_8UC4'</param>
///<param name="dstImage">dstImage is a valid Bitmap object of the same size as the Mat and of type 'ARGB_8888' or 'RGB_565'</param>
///<param name="needPremultiplyAlpha">premultiplyAlpha is a flag, that determines, whether the Mat needs to be converted to alpha premultiplied format (like Android keeps 'ARGB_8888' bitmaps); the flag is ignored for 'RGB_565' bitmaps.</param>
public static void MatToBitmap(Mat srcImage, Bitmap dstImage, bool needPremultiplyAlpha = false)
{
    var bitmapInfo = dstImage.GetBitmapInfo();
    var bitmapPixels = dstImage.LockPixels();
 
    if (bitmapInfo.Format != Format.Rgba8888 && bitmapInfo.Format != Format.Rgb565)
        throw new Exception("Invalid Bitmap Format: It is of format " + bitmapInfo.Format.ToString() + " and is expected Rgba8888 or Rgb565");
    if (srcImage.Dims() != 2)
        throw new Exception("The source image has " + srcImage.Dims() + " dimensions, while it is expected 2");
    if (srcImage.Cols != bitmapInfo.Width || srcImage.Rows != bitmapInfo.Height)
        throw new Exception("The source image and the output Bitmap don't have the same amount of rows and columns");
    if (srcImage.Type() != MatType.CV_8UC1 && srcImage.Type() != MatType.CV_8UC3 && srcImage.Type() != MatType.CV_8UC4)
        throw new Exception("The source image has the type " + srcImage.Type().ToString() + ", while it is expected CV_8UC1, CV_8UC3 or CV_8UC4");
    if (bitmapPixels == null)
        throw new Exception("Can't lock the output bitmap");
 
    if (bitmapInfo.Format == Format.Rgba8888)
    {
        Mat tmp = new Mat((int)bitmapInfo.Height, (int)bitmapInfo.Width, MatType.CV_8UC4, bitmapPixels);
        if (srcImage.Type() == MatType.CV_8UC1)
        {
            Android.Util.Log.Info("MatToBitmap", "CV_8UC1 -> RGBA_8888");
            Cv2.CvtColor(srcImage, tmp, ColorConversionCodes.GRAY2RGBA);
        }
        else if (srcImage.Type() == MatType.CV_8UC3)
        {
            Android.Util.Log.Info("MatToBitmap", "CV_8UC3 -> RGBA_8888");
            Cv2.CvtColor(srcImage, tmp, ColorConversionCodes.RGB2RGBA);
        }
        else if (srcImage.Type() == MatType.CV_8UC4)
        {
            Android.Util.Log.Info("MatToBitmap", "CV_8UC4 -> RGBA_8888");
            if (needPremultiplyAlpha)
                Cv2.CvtColor(srcImage, tmp, ColorConversionCodes.RGBA2mRGBA);
            else
                srcImage.CopyTo(tmp);
        }
    }
    else
    {
        // info.format == ANDROID_BITMAP_FORMAT_RGB_565
        Mat tmp = new Mat((int)bitmapInfo.Height, (int)bitmapInfo.Width, MatType.CV_8UC2, bitmapPixels);
        if (srcImage.Type() == MatType.CV_8UC1)
        {
            Android.Util.Log.Info("MatToBitmap", "CV_8UC1 -> RGB_565");
            Cv2.CvtColor(srcImage, tmp, ColorConversionCodes.GRAY2BGR565);
        }
        else if (srcImage.Type() == MatType.CV_8UC3)
        {
            Android.Util.Log.Info("MatToBitmap", "CV_8UC3 -> RGB_565");
            Cv2.CvtColor(srcImage, tmp, ColorConversionCodes.RGB2BGR565);
        }
        else if (srcImage.Type() == MatType.CV_8UC4)
        {
            Android.Util.Log.Info("MatToBitmap", "CV_8UC4 -> RGB_565");
            Cv2.CvtColor(srcImage, tmp, ColorConversionCodes.RGBA2BGR565);
        }
    }
    dstImage.UnlockPixels();
    return;
}

// Method adapted from the original OpenCV convert at https://github.com/opencv/opencv/blob/b39cd06249213220e802bb64260727711d9fc98c/modules/java/generator/src/cpp/utils.cpp
///<summary>
///This function converts an Android Bitmap image to the OpenCV Mat.
///'ARGB_8888' and 'RGB_565' input Bitmap formats are supported.
///The output Mat is always created of the same size as the input Bitmap and of the 'CV_8UC4' type,it keeps the image in RGBA format.
///This function throws an exception if the conversion fails.
///</summary>
///<param name="srcImage">srcImage is a valid input Bitmap object of the type 'ARGB_8888' or 'RGB_565'</param>
///<param name="dstImage">dstImage is a valid output Mat object, it will be reallocated if needed, so it may be empty.</param>
///<param name="needUnPremultiplyAlpha">unPremultiplyAlpha is a flag, that determines, whether the bitmap needs to be converted from alpha premultiplied format (like Android keeps 'ARGB_8888' ones) to regular one; this flag is ignored for 'RGB_565' bitmaps.</param>
public static void BitmapToMat(Bitmap srcImage, Mat dstImage, bool needUnPremultiplyAlpha = false)
{
    var bitmapInfo = srcImage.GetBitmapInfo();
    var bitmapPixels = srcImage.LockPixels();
 
    if (bitmapInfo.Format != Format.Rgba8888 && bitmapInfo.Format != Format.Rgb565)
        throw new Exception("Invalid Bitmap Format: It is of format " + bitmapInfo.Format.ToString() + " and is expected Rgba8888 or Rgb565");
    if (bitmapPixels == null)
        throw new Exception("Can't lock the source bitmap");
 
    dstImage.Create((int)bitmapInfo.Height, (int)bitmapInfo.Width, MatType.CV_8UC4);
 
    if (bitmapInfo.Format == Format.Rgba8888)
    {
        Android.Util.Log.Info("nBitmapToMat", "RGBA_8888 -> CV_8UC4");
        Mat tmp = new Mat((int)bitmapInfo.Height, (int)bitmapInfo.Width, MatType.CV_8UC4, bitmapPixels);
        if (needUnPremultiplyAlpha)
            Cv2.CvtColor(tmp, dstImage, ColorConversionCodes.mRGBA2RGBA);
        else
            tmp.CopyTo(dstImage);
    }
    else
    {
        // info.format == ANDROID_BITMAP_FORMAT_RGB_565
        Android.Util.Log.Info("nBitmapToMat", "RGB_565 -> CV_8UC4");
        Mat tmp = new Mat((int)bitmapInfo.Height, (int)bitmapInfo.Width, MatType.CV_8UC2, bitmapPixels);
        Cv2.CvtColor(tmp, dstImage, ColorConversionCodes.BGR5652RGBA);
    }
 
    srcImage.UnlockPixels();
    return;
}
//从原始OpenCV转换而来的方法https://github.com/opencv/opencv/blob/b39cd06249213220e802bb64260727711d9fc98c/modules/java/generator/src/cpp/utils.cpp
///
///此函数用于将OpenCV Mat表示中的图像转换为Android位图。
///输入Mat对象的类型必须为“CV_8UC1”(灰度)、“CV_8UC3”(RGB)或“CV_8UC4”(RGBA)。
///输出位图对象的大小必须与输入Mat相同,并且类型必须为“ARGB_8888”或“RGB_565”。
///如果转换失败,此函数将引发异常。
///
///srcImage是“CV_8UC1”、“CV_8UC3”或“CV_8UC4”类型的有效输入Mat对象
///dstImage是与Mat大小相同且类型为“ARGB_8888”或“RGB_565”的有效位图对象
///premultiplyAlpha是一个标志,用于确定Mat是否需要转换为alpha预乘格式(如Android保留“ARGB_8888”位图);对于“RGB_565”位图,该标志将被忽略。
公共静态void MatToBitmap(Mat srcImage、位图dstmimage、bool needPremultiplyAlpha=false)
{
var bitmapInfo=dstImage.GetBitmapInfo();
var bitmapPixels=dstImage.LockPixels();
if(bitmapInfo.Format!=Format.rgba888&&bitmapInfo.Format!=Format.Rgb565)
抛出新异常(“无效位图格式:格式为“+bitmapInfo.Format.ToString()+”,应为RGBA888或Rgb565”);
如果(srcImage.Dims()!=2)
抛出新异常(“源映像具有“+srcImage.Dims()+”维度,而预期为2”);
if(srcImage.Cols!=bitmapInfo.Width | | srcImage.Rows!=bitmapInfo.Height)
抛出新异常(“源图像和输出位图的行数和列数不相同”);
if(srcImage.Type()!=MatType.CV_8UC1和&srcImage.Type()!=MatType.CV_8UC3和&srcImage.Type()!=MatType.CV_8UC4)
抛出新异常(“源映像的类型为“+srcImage.type().ToString()+”,而预期为CV_8UC1、CV_8UC3或CV_8UC4”);
如果(bitmapPixels==null)
抛出新异常(“无法锁定输出位图”);
if(bitmapInfo.Format==Format.Rgba8888)
{
Mat tmp=新Mat((int)bitmapInfo.Height,(int)bitmapInfo.Width,MatType.CV_8UC4,bitmapPixels);
if(srcImage.Type()==MatType.CV_8UC1)
{
Android.Util.Log.Info(“MatToBitmap”、“CV_8UC1->RGBA_8888”);
Cv2.CvtColor(srcImage、tmp、ColorConversionCodes.GRAY2RGBA);
}
else if(srcImage.Type()==MatType.CV_8UC3)
{
Android.Util.Log.Info(“MatToBitmap”、“CV_8UC3->RGBA_8888”);
Cv2.CvtColor(srcImage、tmp、ColorConversionCodes.RGB2RGBA);
}
else if(srcImage.Type()==Mat