takuya-takeuchi / DlibDotNet

Dlib .NET wrapper written in C++ and C# for Windows, MacOS, Linux and iOS
MIT License
484 stars 134 forks source link

arm64 linux support ? #193

Open timiil opened 4 years ago

timiil commented 4 years ago

very great project , but , as the title ,do we have any plan to support arm64 aarch64 linux ?

takuya-takeuchi commented 4 years ago

@timiil Past days, I tried to build DDN as arm64 on docker. It was successful. https://github.com/takuya-takeuchi/DlibDotNet/blob/master/docker/base/ubuntu/16/arm64/Dockerfile.bak

NOTE I don't know this docker file works and build DDN will be successful.

TBH, I don't think there is worth to support arm. Because

and dlib could run on iPhone but any developer reported that dlib was slow. https://github.com/davisking/dlib/issues/1813 https://github.com/davisking/dlib/issues/719 https://github.com/davisking/dlib/issues/1465

takuya-takeuchi commented 4 years ago

NOTE

But qemu may be able to run binary on x84_64 machine. So we can test it?

Japanese memo

timiil commented 4 years ago

i have ARM64 machines and running Ubuntu 16.04 (rockchip 3328/3399), they can run the frdn using , but the speed is much slower than running python code (FaceDetect+Encoding) in the same machine .

my tests steps are:

echo '

netcoreapp3.1 AnyCPU;arm TRACE;ARM

' > dlib.arm.csproj

echo 'using CommandLine; using FaceRecognitionDotNet; using System; using System.Threading; using System.Linq;

namespace FaceEncodingCompare { class Options { [Option('"'"'f'"'"', "folder", Required = true, HelpText = "trianed model data files folder")] public string DataFolder { get; set; }

    [Option('"'"'t'"'"', "test", Required = true, HelpText = "test picture file path")]
    public string TestPicture { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var options = Parser.Default.ParseArguments<Options>(args) as Parsed<Options>;
        if (options == null || options.Value == null)
            return;

        var cfg = options.Value;

        using (var fr = FaceRecognition.Create(cfg.DataFolder))
        using (var img = FaceRecognition.LoadImageFile(cfg.TestPicture))
        {
            Thread.Sleep(1000);

            var startTime = DateTime.Now;
            var locations = fr.FaceLocations(img);
                //.ToArray();
            var locationTime = DateTime.Now;
            var encodings = fr.FaceEncodings(img, locations)
              .ToArray();                   
            var encodingTime = DateTime.Now;

            Console.WriteLine($"FaceDetect = [{(locationTime - startTime).TotalMilliseconds}]ms, FaceEncode = [{(encodingTime - locationTime).TotalMilliseconds}]ms, Total = [{(encodingTime - startTime).TotalMilliseconds}]ms, Landmarks = [{encodings.Length}]");                

        }

    }
}

}' > Program.cs

dotnet run -p dlib.arm.csproj -- -f /home/data -t /home/testpics/m2.jpg



if you could do me a favour to give an ARM64 nuget , i am very happy to test the code on these machines. 

or tell me how to build the ARM64 version FRDN or DlibDotNet_ARM64 version, also very wellcome.

i can PR the test code to sample folder, even include the test python code if you need.
takuya-takeuchi commented 4 years ago

@timiil FRDN.ARM uses DDN.ARM https://www.nuget.org/packages/DlibDotNet-ARM https://www.nuget.org/packages/FaceRecognitionDotNet-ARM/1.2.3.11-alpha

DDN.ARM contains arm and arm64 binary.

python code

What is this? Are you talking about face_recognition?

timiil commented 4 years ago

@timiil FRDN.ARM uses DDN.ARM https://www.nuget.org/packages/DlibDotNet-ARM https://www.nuget.org/packages/FaceRecognitionDotNet-ARM/1.2.3.11-alpha

DDN.ARM contains arm and arm64 binary.

python code

What is this? Are you talking about face_recognition?

yes, my python test code in arm64:

echo "import face_recognition
import datetime
import numpy as np
import time
import sys

def landmark(image):
    unknown_image = face_recognition.load_image_file(image)
    time.sleep(1)
    t1 = datetime.datetime.now().microsecond
    t3 = time.mktime(datetime.datetime.now().timetuple())
    image_location = face_recognition.face_locations(unknown_image)
    t2 = datetime.datetime.now().microsecond
    t4 = time.mktime(datetime.datetime.now().timetuple())
    u_face_encoding = face_recognition.face_encodings(unknown_image, known_face_locations=image_location)[0]
    tt2 = datetime.datetime.now().microsecond
    tt4 = time.mktime(datetime.datetime.now().timetuple())
    location_time = (t4 - t3) * 1000 + (t2 - t1) / 1000
    encoding_time = (tt4 - t4) * 1000 + (tt2 - t2) / 1000
    total_time = (tt4 - t3) * 1000 + (tt2 - t1) / 1000

    print('FaceDetect = {} ms, FaceEncode = {} ms, Total = {} ms'.format(location_time, encoding_time, total_time))

if __name__ == '__main__':
    if len(sys.argv) == 1:
        print('usage: python3 test.py /test/test.jpg')

    image = sys.argv[1]
    landmark(image)  " > test.py

python3 test.py /home/testpic/m2.jpg
takuya-takeuchi commented 4 years ago

dotnet run -p dlib.arm.csproj -- -f /home/data -t /home/testpics/m2.jpg

Does it work as arm? You could use -r option (-r linux-arm64) and run in the output directory.

timiil commented 4 years ago

dotnet run -p dlib.arm.csproj -- -f /home/data -t /home/testpics/m2.jpg

Does it work as arm? You could use -r option (-r linux-arm64) and run in the output directory.

Yes , it work as ARM.

here is a little benchmark on rk3399/ubuntu 16.04 (the test picture had 9 faces inside):

** 1, python:

python3 test.py /home/testpic/m2.jpg

FaceDetect = 742 ms, FaceEncode = 1011 ms, Total = 1754 ms

** 2, dotnet (project):

dotnet run -p dlib.arm.csproj -- -f /home/dlib/data/ -t /home/testpic/m2.jpg

FaceDetect = [37] ms, FaceEncode = [7319] ms, Total = [7356] ms, Landmarks = [9]

** 3, dotnet (run dll):

cd /home/dlib/bin/Debug/netcoreapp3.1/linux-arm64
dotnet dlib.arm.dll -f /home/dlib/data/ -t /home/testpic/m2.jpg

FaceDetect = [30] ms, FaceEncode = [6517] ms, Total = [6548] ms, Landmarks = [9]

It is still far away slower than python. but i had test the same dotnet code and python code on a 'intel 9400 / centos 7.3 / docker-ce 19.03' computer, running by dotnetcoresdk3.1 container and python3.5 container; our FRDN is faster than python .

Could you find out why is so slow we running on ARM64 ? It is really interesting we can run on ARM64 devices using by C#.

takuya-takeuchi commented 4 years ago

@timiil

I can not understand why FaceDetect is more fast than python code. Basically, FaceDetect uses shape_predictor which depends on cpu rather than gpu. So this measure value should be close to. I'm nos sure that there could be difference parameter between C# and python.

But FaceEncoding uses deep learning. So if native dlib library uses gpu or special instruction, face encoding is accelerated. In ARM64, dlib may use NEON. But I'm not sure that DDN uses NEON. And I don't know how to check whether NEON works.

timiil commented 4 years ago

@timiil

I can not understand why FaceDetect is more fast than python code. Basically, FaceDetect uses shape_predictor which depends on cpu rather than gpu. So this measure value should be close to. I'm nos sure that there could be difference parameter between C# and python.

But FaceEncoding uses deep learning. So if native dlib library uses gpu or special instruction, face encoding is accelerated. In ARM64, dlib may use NEON. But I'm not sure that DDN uses NEON. And I don't know how to check whether NEON works.

FaceDetect fast may because:Linq :) the real deal is in IEnumable,which not yield return yet.

May be I should make a test on a qemu arm64 ?