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.stdint;
28 import std.conv;
29 import std.string;
30 
31 import opencvd.cvcore;
32 
33 private extern (C) {
34     Net Net_ReadNet(const char* model, const char* config);
35     Net Net_ReadNetBytes(const char* framework, ByteArray model, ByteArray config);
36     Net Net_ReadNetFromCaffe(const char* prototxt, const char* caffeModel);
37     Net Net_ReadNetFromCaffeBytes(ByteArray prototxt, ByteArray caffeModel);
38     Net Net_ReadNetFromTensorflow(const char* model);
39     Net Net_ReadNetFromTensorflowBytes(ByteArray model);
40     Mat Net_BlobFromImage(Mat image, double scalefactor, Size size, Scalar mean, bool swapRB,
41                           bool crop);
42     void Net_Close(Net net);
43     bool Net_Empty(Net net);
44     void Net_SetInput(Net net, Mat blob, const char* name);
45     Mat Net_Forward(Net net, const char* outputName);
46     void Net_ForwardLayers(Net net, Mats* outputBlobs, CStrings outBlobNames);
47     void Net_SetPreferableBackend(Net net, int backend);
48     void Net_SetPreferableTarget(Net net, int target);
49     int64_t Net_GetPerfProfile(Net net);
50     void Net_GetUnconnectedOutLayers(Net net, IntVector* res);
51 
52     Mat Net_GetBlobChannel(Mat blob, int imgidx, int chnidx);
53     Scalar Net_GetBlobSize(Mat blob);
54 
55     Layer Net_GetLayer(Net net, int layerid);
56     void Layer_Close(Layer layer);
57     int Layer_InputNameToIndex(Layer layer, const char* name);
58     int Layer_OutputNameToIndex(Layer layer, const char* name);
59     const(char*) Layer_GetName(Layer layer);
60     const(char*) Layer_GetType(Layer layer);
61 }
62 
63 enum: int { 
64     DNN_BACKEND_DEFAULT, 
65     DNN_BACKEND_HALIDE, 
66     DNN_BACKEND_INFERENCE_ENGINE, 
67     DNN_BACKEND_OPENCV, 
68     DNN_BACKEND_VKCOM,
69 }
70 
71 enum: int {
72     DNN_TARGET_CPU,
73     DNN_TARGET_OPENCL,
74     DNN_TARGET_OPENCL_FP16,
75     DNN_TARGET_MYRIAD,
76     DNN_TARGET_VULKAN,
77     DNN_TARGET_FPGA
78 }
79 
80 struct Net {
81     void* p;
82     
83     bool empty(){
84         return Net_Empty(this) == 0 ? false: true;
85     }
86     
87     void setInput(Mat blob, string name = ""){
88         Net_SetInput(this, blob, name.toStringz);
89     }
90     
91     Mat forward(string outputName = ""){
92         Mat _net = Net_Forward(this, outputName.toStringz);
93         return _net;
94     }
95     
96     void forward(ref Mat[] outputBlobs, string[] outBlobNames){
97         CStrings coutBlobNames = {cast(const(char**))outBlobNames.ptr, outBlobNames.length.to!int};
98         Mats obs;
99         Net_ForwardLayers(this, &obs, coutBlobNames);
100         
101         outputBlobs = obs.mats[0..obs.length].dup;
102         Mats_Close(obs);
103     }
104     
105     void setPreferableBackend(int backend){
106         Net_SetPreferableBackend(this, backend);
107     }
108     
109     void setPreferableTarget(int target){
110         Net_SetPreferableTarget(this, target);
111     }
112     
113     int64_t getPerfProfile(){
114         return Net_GetPerfProfile(this);
115     }
116     
117     void getUnconnectedOutLayers(ref int[] res){
118         IntVector _res;
119         Net_GetUnconnectedOutLayers(this, &_res);
120         
121         res = _res.val[0.._res.length].dup;
122         Close_IntVector(_res);
123     }
124 
125     Layer getLayer(int layerid){
126         return Net_GetLayer(this, layerid);
127     }
128 }
129 
130 Mat getBlobChannel(Mat blob, int imgidx, int chnidx){
131     return Net_GetBlobChannel(blob, imgidx, chnidx);
132 }
133 
134 Scalar getBlobSize(Mat blob){
135     return Net_GetBlobSize(blob);
136 }
137 
138 void Destroy(Net net){
139     Net_Close(net);
140 }
141 
142 Net readNet(string model, string config){
143     return Net_ReadNet(toStringz(model), toStringz(config));
144 }
145     
146 Net readNetBytes(string framework, ubyte[] model, ubyte[] config){
147     return Net_ReadNetBytes(framework.toStringz, ByteArray(model.ptr, model.length.to!int), ByteArray(config.ptr, config.length.to!int));
148 }
149 
150 Net readNetFromCaffe(string prototxt, string caffeModel){
151     return Net_ReadNetFromCaffe(prototxt.toStringz, caffeModel.toStringz);
152 }
153 
154 Net readNetFromCaffeBytes(ubyte[] prototxt, ubyte[] caffeModel){
155     return Net_ReadNetFromCaffeBytes(ByteArray(prototxt.ptr, prototxt.length.to!int),
156         ByteArray(caffeModel.ptr, caffeModel.length.to!int));
157 }
158 
159 Net readNetFromTensorflow(string model){
160     return Net_ReadNetFromTensorflow(model.toStringz);
161 }
162 
163 Net readNetFromTensorflowBytes(ubyte[] model){
164     return Net_ReadNetFromTensorflowBytes(ByteArray(model.ptr, model.length.to!int));
165 }
166 
167 Mat blobFromImage(Mat image, double scalefactor=1.0, Size size = Size(), Scalar mean = Scalar(), bool swapRB = false, bool crop = false){
168     return Net_BlobFromImage(image, scalefactor, size, mean, swapRB, crop);
169 }
170 
171 struct Layer {
172     void* p;
173         
174     int inputNameToIndex(string name){
175         return Layer_InputNameToIndex(this, name.toStringz);
176     }
177     
178     int outputNameToIndex(string name){
179         return Layer_OutputNameToIndex(this, name.toStringz);
180     }
181     
182     string getName(){
183         return Layer_GetName(this).to!string;
184     }
185     
186     string getType(){
187         return Layer_GetType(this).to!string;
188     }
189     
190 }
191 
192 void Destroy(Layer layer){
193     Layer_Close(layer);
194 }