2

I am attempting to use Emgu on linux, but getting the error message:

Unhandled exception. System.TypeInitializationException:
The type initializer for 'Emgu.CV.CvInvoke' threw an exception.
---> System.DllNotFoundException: Unable to load shared library 'cvextern' or one of its dependencies

After looking around in SO and the documentation I understand that I need to:

Make sure the unmanaged DLLs are in the execution directory.

But - how do I get them?
If I run the same project on a windows machine (+ un commenting the reference to the Emgu.CV.runtime.windows package), I indeed get x86 & x64 folders in my bin folder which I can get the binaries from, but apparently when using Emgu.CV.runtime.ubuntu package, those folders are not created.


Minimal, Reproducible Example:
Program.cs:

using Emgu.CV;
using Emgu.CV.Structure;
using System;

namespace temp
{
    class Program
    {
        static void Main(string[] args)
        {
            // Works on windows, fails on linux
            var imageFromBytes = new Image<Rgb, byte>(2, 2);


            //// Later on I would like this to work as well...
            // var bytes = new byte[] { 1, 2, 3, 4 };
            // CvInvoke.Imdecode(bytes, Emgu.CV.CvEnum.ImreadModes.Color, imageFromBytes.Mat);
        }

    }
}

The project file:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Emgu.CV.runtime.ubuntu" Version="4.4.0.4061" />

    <!-- When running on windows & uncommenting this line - I get can get the binaries-->
    <!-- <PackageReference Include="Emgu.CV.runtime.windows" Version="4.4.0.4061" /> -->

  </ItemGroup>

</Project>


Additional information:
dotnet version: 3.1.301
Emgu version: 4.4.0.4061

Avi Turner
  • 10,234
  • 7
  • 48
  • 75

2 Answers2

10

So, after few days of struggling - answering my own question.

As far as I understand, there were two issues here:

  1. libcvextern.so was missing.
  2. libcvextern.so dependencies were missing.

Fixing the issues:

1. Missing libcvextern.so:

  1. Downloaded the Emgu.CV.runtime.ubuntu
  2. unzip it and get the libcvextern.so file (build/x64/libcvextern.so).
  3. Add the libcvextern.so file to the project and set Copy to Output directory to Copy if Newer

Note: For the windows nuget package the files that you need are added automatically. Not sure why this does not happen for linux.

2. Missing dependencies:

  1. As per the documentation (Linux -> Getting ready), I have cloned the repo and ran the script that makes sure that all dependencies are installed:

get dotnet Framework:

wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
dpkg -i packages-microsoft-prod.deb

Get the source code:

git clone https://github.com/emgucv/emgucv emgucv 
cd emgucv
git submodule update --init --recursive

Make sure the dependencies are available:

# cd into the relevant platform
cd platforms/ubuntu/20.04

# As per documentation: This only needs to be run once.
./apt_install_dependency

# This is what actually builds the dependencies. This will take a while...
./cmake_configure


Bonus:
If you, like me, don't have root permissions to your machine, you can use docker.

Update Dec-2022:
I'll try and keep posting docker files for new versions as they come out with my conclusions after making emgu work...

The Dockerfile I have used:

.NET 6, emgu 4.6, Dec-2022:

FROM ubuntu
ENV LC_ALL=C.UTF-8 LANG=C.UTF-8

RUN apt-get update && apt-get -y install sudo

# Dotnet Framework
# https://docs.microsoft.com/en-us/dotnet/core/install/linux-ubuntu
WORKDIR /tmp
RUN wget https://packages.microsoft.com/config/ubuntu/20.10/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
RUN dpkg -i packages-microsoft-prod.deb
RUN apt-get update; \
  apt-get install -y apt-transport-https && \
  apt-get update && \
  apt-get install -y dotnet-sdk-6.0


# Make sure all emgu dependencies are in place
# http://www.emgu.com/wiki/index.php/Download_And_Installation#Getting_ready
WORKDIR /mnt/emgu_repo
RUN git clone https://github.com/emgucv/emgucv emgucv
WORKDIR /mnt/emgu_repo/emgucv
RUN git fetch origin 4.6.0
RUN git checkout 4.6.0
RUN git submodule update --init --recursive

# install cmake for compiling open cv dependencies
RUN apt-get update && apt-get install -y cmake protobuf-compiler ffmpeg libgtk-3-dev libgstreamer1.0-dev libavcodec-dev libswscale-dev libavformat-dev libdc1394-22-dev libv4l-dev ocl-icd-dev freeglut3-dev libgeotiff-dev libusb-1.0-0-dev

WORKDIR /mnt/emgu_repo/emgucv/platforms/ubuntu/20.04
RUN ./apt_install_dependency
# this takes a long time
RUN ./cmake_configure


WORKDIR /mnt/my_app_root
# emgu needs the libcvextern.so file & dependency in the rrot folder
RUN cp /mnt/emgu_repo/emgucv/libs/runtimes/ubuntu-x64/native/* ./


ENTRYPOINT ["bash"]

.NET core 3.1, emgu 4.3, Sep-2020:

FROM ubuntu
ENV LC_ALL=C.UTF-8 LANG=C.UTF-8


# Bring the dotnet Framework
RUN wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
RUN dpkg -i packages-microsoft-prod.deb
RUN apt-get update; \
  apt-get install -y apt-transport-https && \
  apt-get update && \
  apt-get install -y dotnet-sdk-3.1


# Make sure all emgu dependencies are in place
# http://www.emgu.com/wiki/index.php/Download_And_Installation#Getting_ready
WORKDIR /mnt/emgu_repo
RUN git clone https://github.com/emgucv/emgucv emgucv
WORKDIR /mnt/emgu_repo/emgucv
RUN git submodule update --init --recursive
WORKDIR /mnt/emgu_repo/emgucv/platforms/ubuntu/18.04
RUN apt-get update && apt-get -y install sudo
RUN `cat ./apt_install_dependency.sh | grep -Ev "\#\!"` -y
RUN ./cmake_configure.sh


ENTRYPOINT ["bash"]
Avi Turner
  • 10,234
  • 7
  • 48
  • 75
  • did you manage to find reason why libcvextern was not copied? I have same issue, manually copying it fixes everything. However we have automatic builds and I can't do it each time. I'm on 4.4 because 4.5.1 version does not support ubuntu 18.04. – Vladimir Glushkov Apr 30 '21 at 15:55
  • Sorry, no... Also this was a while ago, and I do not recall all of the details. – Avi Turner May 02 '21 at 07:02
  • No problem, I found out that targets file in nuget is incorrect, so it actually never copies the .so file to output directory. It does not happen with newer nuget though which is based on runtime-identifier. – Vladimir Glushkov May 03 '21 at 16:45
  • to check missing depedencies run ldd libcvextern.so – howardButcher Nov 18 '22 at 12:02
2

Share my answers

Avi Turner's answer was helpful. Run the below command and check if there is any dependency missing. (e.g Trying to get Emgu.CV running in dotnet core 3.1 on debian)

ldd libcvextern.so

Install missing dependencies

apt-get update&&apt-get install libgdiplus libx11-dev libgeotiff-dev libxt-dev libopengl-dev libglx-dev libusb-1.0-0

D S
  • 258
  • 9
  • 25
zxzhuty
  • 21
  • 1