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.objdetect;
26 
27 import std..string;
28 import std.typecons;
29 import std.conv;
30 
31 import opencvd.cvcore;
32 
33 private extern (C){
34     CascadeClassifier CascadeClassifier_New();
35     bool CascadeClassifier_Empty(CascadeClassifier cs);
36     void CascadeClassifier_Close(CascadeClassifier cs);
37     int CascadeClassifier_Load(CascadeClassifier cs, const char* name);
38     Rects CascadeClassifier_DetectMultiScale(CascadeClassifier cs, Mat img);
39     Rects CascadeClassifier_DetectMultiScaleWithParams(CascadeClassifier cs, Mat img,
40             double scale, int minNeighbors, int flags, Size minSize, Size maxSize);
41 
42     HOGDescriptor HOGDescriptor_New();
43     void HOGDescriptor_Close(HOGDescriptor hog);
44     int HOGDescriptor_Load(HOGDescriptor hog, const char* name);
45     Rects HOGDescriptor_DetectMultiScale(HOGDescriptor hog, Mat img);
46     Rects HOGDescriptor_DetectMultiScaleWithParams(HOGDescriptor hog, Mat img,
47             double hitThresh, Size winStride, Size padding, double scale, double finalThreshold,
48             bool useMeanshiftGrouping);
49     Mat HOG_GetDefaultPeopleDetector();
50     void HOGDescriptor_SetSVMDetector(HOGDescriptor hog, Mat det);
51     Size HOGDescriptor_GetWinSize(HOGDescriptor hd);
52     void HOGDescriptor_SetWinSize(HOGDescriptor hd, Size newSize);
53     void HOGDescriptor_Compute(HOGDescriptor hd, Mat img, FloatVector descriptors, Size winStride, Size padding, Points locations);
54     void HOGDescriptor_DetectMultiScale2(HOGDescriptor hd,
55                                     Mat img,
56                                     Rects* foundLocations,
57                                     DoubleVector* foundWeights,
58                                     double hitThreshold,
59                                     Size winStride,
60                                     Size padding,
61                                     double scale,
62                                     double finalThreshold,
63                                     bool useMeanshiftGrouping);
64     void HOGDescriptor_Save(HOGDescriptor hd, const char* filename);
65                                     
66     Rects GroupRectangles(Rects rects, int groupThreshold, double eps);
67 }
68 
69 struct CascadeClassifier {
70     void* p;
71     
72     static CascadeClassifier opCall(){
73         return CascadeClassifier_New();
74     }
75     
76     bool empty(){
77         return CascadeClassifier_Empty(this);
78     }
79     
80     int load(string name){
81         return CascadeClassifier_Load(this, toStringz(name));
82     }
83     
84     Rects detectMultiScale(Mat img){
85         return CascadeClassifier_DetectMultiScale(this, img);
86     }
87     
88     Rects detectMultiScale(Mat img, double scale, int minNeighbors,
89                                     int flags, Size minSize, Size maxSize){
90         return CascadeClassifier_DetectMultiScaleWithParams(this, img, scale, 
91             minNeighbors, flags, minSize, maxSize);
92     }
93 }
94 
95 void Destroy(CascadeClassifier c){
96     CascadeClassifier_Close(c);
97 }
98 
99 CascadeClassifier newCascadeClassifier(){
100     return CascadeClassifier_New();
101 }
102 
103 struct HOGDescriptor {
104     void* p;
105     
106     static HOGDescriptor opCall(){
107         return HOGDescriptor_New();
108     }
109     
110     int load(string name){
111         return HOGDescriptor_Load(this, toStringz(name));
112     }
113     /*
114     Rects detectMultiScale(Mat img){
115         return HOGDescriptor_DetectMultiScale(this, img);
116     }
117     
118     Rects detectMultiScaleWithParams(Mat img, double hitThresh, Size winStride,
119                 Size padding, double scale, double finalThreshold, bool useMeanshiftGrouping){
120         return HOGDescriptor_DetectMultiScaleWithParams(this, img, hitThresh, 
121                             winStride, padding, scale, finalThreshold, useMeanshiftGrouping);
122     }
123     */
124     void setSVMDetector(Mat det){
125         HOGDescriptor_SetSVMDetector(this, det);
126     }
127     
128     Size winSize() @property {
129         return HOGDescriptor_GetWinSize(this);
130     }
131 
132     void winSize(Size newSize) @property {
133         HOGDescriptor_SetWinSize(this, newSize);
134     }
135     
136     void compute(Mat img, float[] descriptors, Size winStride = Size(), Size padding = Size(), Point[] locations = []){
137         HOGDescriptor_Compute(this, img, FloatVector(descriptors.ptr, descriptors.length.to!int),
138                 winStride, padding, Points(locations.ptr, locations.length.to!int));
139     }
140     
141     Tuple!(Rect[], double[]) detectMultiScale(Mat img,
142                             double hitThreshold = 0,
143                             Size winStride = Size(),
144                             Size padding = Size(),
145                             double scale = 1.05,
146                             double finalThreshold = 2.0,
147                             bool useMeanshiftGrouping = false){
148         Rects* fl;
149         DoubleVector* fw;
150         HOGDescriptor_DetectMultiScale2(this,
151                                     img,
152                                     fl,
153                                     fw,
154                                     hitThreshold,
155                                     winStride,
156                                     padding,
157                                     scale,
158                                     finalThreshold,
159                                     useMeanshiftGrouping);
160         Rect[] dfl = fl.rects[0..fl.length].dup;
161         double[] dfw = fw.val[0..fw.length].dup;
162         
163         Rects_Close(*fl);
164         Close_DoubleVector(*fw);
165         
166         return tuple(dfl, dfw);
167     }
168     
169     void save(string filename){
170         HOGDescriptor_Save(this, filename.toStringz);
171     }
172 }
173 
174 void Destroy(HOGDescriptor hd){
175     HOGDescriptor_Close(hd);
176 }
177 
178 HOGDescriptor newHOGDescriptor(){
179     return HOGDescriptor_New();
180 }
181 
182 Mat getDefaultPeopleDetectorHOG(){
183     return HOG_GetDefaultPeopleDetector();
184 }
185 
186 Rects groupRectangles(Rects rects, int groupThreshold, double eps){
187     return GroupRectangles(rects, groupThreshold, eps);
188 }