1 /*
2 Copyright (c) 2019 Ferhat Kurtulmuş
3 Boost Software License - Version 1.0 - August 17th, 2003
4 Permission is hereby granted, free of charge, to any person or organization
5 obtaining a copy of the software and accompanying documentation covered by
6 this license (the "Software") to use, reproduce, display, distribute,
7 execute, and transmit the Software, and to prepare derivative works of the
8 Software, and to permit third-parties to whom the Software is furnished to
9 do so, all subject to the following:
10 The copyright notices in the Software and this entire statement, including
11 the above license grant, this restriction and the following disclaimer,
12 must be included in all copies of the Software, in whole or in part, and
13 all derivative works of the Software, unless such copies or derivative
14 works are solely in the form of machine-executable object code generated by
15 a source language processor.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
19 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
20 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
21 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24 
25 module opencvd.dnn;
26 
27 import core.stdc.stdlib;
28 import core.stdc.stdint;
29 import std.conv;
30 import std.typecons;
31 import std..string;
32 
33 import opencvd.cvcore;
34 
35 private extern (C) {
36     Net Net_ReadNet(const char* model, const char* config);
37     Net Net_ReadNetBytes(const char* framework, ByteArray model, ByteArray config);
38     Net Net_ReadNetFromCaffe(const char* prototxt, const char* caffeModel);
39     Net Net_ReadNetFromCaffeBytes(ByteArray prototxt, ByteArray caffeModel);
40     Net Net_ReadNetFromTensorflow(const char* model);
41     Net Net_ReadNetFromTensorflowBytes(ByteArray model);
42     Mat Net_BlobFromImage(Mat image, double scalefactor, Size size, Scalar mean, bool swapRB,
43                           bool crop);
44     IntVector DNN_NMSBoxes(RotatedRects rects, FloatVector scores, float score_threshold, float nms_threshold, float eta, int top_k);
45     void Net_Close(Net net);
46     bool Net_Empty(Net net);
47     void Net_SetInput(Net net, Mat blob, const char* name);
48     Mat Net_Forward(Net net, const char* outputName);
49     void Net_ForwardLayers(Net net, Mats* outputBlobs, CStrings outBlobNames);
50     void Net_SetPreferableBackend(Net net, int backend);
51     void Net_SetPreferableTarget(Net net, int target);
52     int64_t Net_GetPerfProfile(Net net);
53     void Net_GetUnconnectedOutLayers(Net net, IntVector* res);
54 
55     Mat Net_GetBlobChannel(Mat blob, int imgidx, int chnidx);
56     Scalar Net_GetBlobSize(Mat blob);
57 
58     Layer Net_GetLayer(Net net, int layerid);
59     void Layer_Close(Layer layer);
60     int Layer_InputNameToIndex(Layer layer, const char* name);
61     int Layer_OutputNameToIndex(Layer layer, const char* name);
62     const(char*) Layer_GetName(Layer layer);
63     const(char*) Layer_GetType(Layer layer);
64 }
65 
66 enum: int { 
67     DNN_BACKEND_DEFAULT, 
68     DNN_BACKEND_HALIDE, 
69     DNN_BACKEND_INFERENCE_ENGINE, 
70     DNN_BACKEND_OPENCV, 
71     DNN_BACKEND_VKCOM,
72 }
73 
74 enum: int {
75     DNN_TARGET_CPU,
76     DNN_TARGET_OPENCL,
77     DNN_TARGET_OPENCL_FP16,
78     DNN_TARGET_MYRIAD,
79     DNN_TARGET_VULKAN,
80     DNN_TARGET_FPGA
81 }
82 
83 struct Net {
84     void* p;
85     
86     bool empty(){
87         return Net_Empty(this) == 0 ? false: true;
88     }
89     
90     void setInput(Mat blob, string name = ""){
91         Net_SetInput(this, blob, name.toStringz);
92     }
93     
94     Mat forward(string outputName = ""){
95         Mat _net = Net_Forward(this, outputName.toStringz);
96         return _net;
97     }
98     
99     void forward(ref Mat[] outputBlobs, string[] outBlobNames){
100         import core.stdc.stdlib;
101         char** cstrs = cast(char**)malloc(outBlobNames.length * (char*).sizeof);
102         for(int i = 0; i < outBlobNames.length; i++){
103             cstrs[i] = cast(char*)outBlobNames[i].toStringz;
104             
105         }
106         
107         CStrings coutBlobNames = {cstrs, outBlobNames.length.to!int};
108         Mats obs;
109         Net_ForwardLayers(this, &obs, coutBlobNames);
110         free(cstrs);
111         outputBlobs = obs.mats[0..obs.length].dup;
112         Mats_Close(obs);
113     }
114     
115     void setPreferableBackend(int backend){
116         Net_SetPreferableBackend(this, backend);
117     }
118     
119     void setPreferableTarget(int target){
120         Net_SetPreferableTarget(this, target);
121     }
122     
123     int64_t getPerfProfile(){
124         return Net_GetPerfProfile(this);
125     }
126     
127     void getUnconnectedOutLayers(ref int[] res){
128         IntVector *_res;
129         Net_GetUnconnectedOutLayers(this, _res);
130         
131         res = _res.val[0.._res.length].dup;
132         Close_IntVector(*_res);
133     }
134 
135     Layer getLayer(int layerid){
136         return Net_GetLayer(this, layerid);
137     }
138 }
139 
140 Mat getBlobChannel(Mat blob, int imgidx, int chnidx){
141     return Net_GetBlobChannel(blob, imgidx, chnidx);
142 }
143 
144 Scalar getBlobSize(Mat blob){
145     return Net_GetBlobSize(blob);
146 }
147 
148 void Destroy(Net net){
149     Net_Close(net);
150 }
151 
152 Net readNet(string model, string config = ""){
153     return Net_ReadNet(toStringz(model), toStringz(config));
154 }
155     
156 Net readNetBytes(string framework, ubyte[] model, ubyte[] config){
157     return Net_ReadNetBytes(framework.toStringz, ByteArray(model.ptr, model.length.to!int), ByteArray(config.ptr, config.length.to!int));
158 }
159 
160 Net readNetFromCaffe(string prototxt, string caffeModel){
161     return Net_ReadNetFromCaffe(prototxt.toStringz, caffeModel.toStringz);
162 }
163 
164 Net readNetFromCaffeBytes(ubyte[] prototxt, ubyte[] caffeModel){
165     return Net_ReadNetFromCaffeBytes(ByteArray(prototxt.ptr, prototxt.length.to!int),
166         ByteArray(caffeModel.ptr, caffeModel.length.to!int));
167 }
168 
169 Net readNetFromTensorflow(string model){
170     return Net_ReadNetFromTensorflow(model.toStringz);
171 }
172 
173 Net readNetFromTensorflowBytes(ubyte[] model){
174     return Net_ReadNetFromTensorflowBytes(ByteArray(model.ptr, model.length.to!int));
175 }
176 
177 Mat blobFromImage(Mat image, double scalefactor=1.0, Size size = Size(), Scalar mean = Scalar(), bool swapRB = false, bool crop = false){
178     return Net_BlobFromImage(image, scalefactor, size, mean, swapRB, crop);
179 }
180 
181 int[] NMSBoxes(RotatedRect[] rects, float[] scores, float score_threshold, float nms_threshold, float eta = 1.0f, int top_k = 0){
182     IntVector _indices = DNN_NMSBoxes(RotatedRects(rects.ptr, rects.length.to!int),
183         FloatVector(scores.ptr, scores.length.to!int), score_threshold, nms_threshold, eta, top_k);
184     
185     int[] indices = _indices.val[0.._indices.length].dup;
186     Close_IntVector(_indices);
187     
188     return indices;
189 }
190 
191 struct Layer {
192     void* p;
193         
194     int inputNameToIndex(string name){
195         return Layer_InputNameToIndex(this, name.toStringz);
196     }
197     
198     int outputNameToIndex(string name){
199         return Layer_OutputNameToIndex(this, name.toStringz);
200     }
201     
202     string getName(){
203         return Layer_GetName(this).to!string;
204     }
205     
206     string getType(){
207         return Layer_GetType(this).to!string;
208     }
209     
210 }
211 
212 void Destroy(Layer layer){
213     Layer_Close(layer);
214 }