Skip to content

Commit 936ea4b

Browse files
committed
OpenCV 4 compatibility and default. OpenCV 3 compat likely broken now
Implementation notes beyond what this commit adds to the CHANGELOG: * `drawAxis()` was replaced by `drawFrameAxes()`. The former is available only until OpenCV <= 4.5, while the latter is available for all 4.x. * opencv/opencv_contrib@56d492c * opencv/opencv_contrib@0f030dd
1 parent 14dfed0 commit 936ea4b

File tree

15 files changed

+143
-62
lines changed

15 files changed

+143
-62
lines changed

opencv-extra-examples/src/tracker.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ main = do
4949

5050
w <- CV.videoCaptureGetI cap VideoCapPropFrameWidth
5151
h <- CV.videoCaptureGetI cap VideoCapPropFrameHeight
52-
let trType = BOOSTING
53-
tr <- newTracker trType -- BOOSTING MIL KFC MEDIANFLOW TLD
52+
let trType = KCF
53+
tr <- newTracker trType
5454
CV.withWindow "video1" $ \w1 ->
5555
loop cap (w, h, tr, trType) w1
5656
where
@@ -77,7 +77,7 @@ main = do
7777
for_ mbTrac $ \trac ->
7878
lift $ CV.rectangle
7979
imgM
80-
(CV.fmapRect round trac)
80+
trac
8181
white
8282
2
8383
CV.LineType_8

opencv-extra/CHANGELOG.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,38 @@
22

33
### Changed
44

5+
- OpenCV 4 requirement:
6+
- OpenCV 3 compatibility was dropped to ease maintenance.
7+
For example, Ubuntu 22.04 (1.5 years old as of writing) does not ship OpenCV 3.
8+
If you want this back, please contributed it:
9+
It will require a reasonable amount of `#if`s that can probably be added in 1 day, but would more importantly need a CI setup added so it keeps working.
10+
- Gained a Cabal flag `enable-nonfree` to enable those modules that require the system OpenCV 4 to be compiled with the OPENCV_ENABLE_NONFREE option (most OpenCV installations lack this by default).
11+
This means SIFT/SURF feature detection are not available by default.
12+
Note that the authors of this Haskell package do not currently fully understand OpenCV's logic here:
13+
On Ubuntu 22.04, OpenCV 4.5 does not include the `opencv2/xfeatures2d/nonfree.hpp` header.
14+
But on NixOS 23.05, `opencv4` version 4.7 does include it, even though `-DOPENCV_ENABLE_NONFREE=OFF` was passed to its build, and so the code builds with the `enable-nonfree` Cabal flag in any case.
15+
- Legacy tracker types were removed.
16+
OpenCV has [split](https://docs.opencv.org/4.8.0/d9/df8/group__tracking.html) their API into "Tracking API" and "Legacy Tracking API.
17+
These have incompatible `Tracker` type hierarchies:
18+
[`cv::Tracker`](https://docs.opencv.org/4.8.0/d0/d0a/classcv_1_1Tracker.html) and
19+
[`cv::legacy::Tracker`](https://docs.opencv.org/4.8.0/db/dfe/classcv_1_1legacy_1_1Tracker.html).
20+
For simplicity, this Haskell binding dropped the legacy API's `TrackerType`s trackers:
21+
- `BOOSTING`
22+
- `MEDIANFLOW`
23+
- `TLD`
24+
If you need these, please let us know and ideally contribute a wrapper for them.
25+
- `initTracker` changed its return type from `Bool` to `()` as the C++ return type is now `void`
26+
- [3.4](https://docs.opencv.org/3.4/d0/d0a/classcv_1_1Tracker.html#a4d285747589b1bdd16d2e4f00c3255dc)
27+
- [4.8](https://docs.opencv.org/4.8.0/d0/d0a/classcv_1_1Tracker.html#a7793a7ccf44ad5c3557ea6029a42a198)
28+
- `initTracker` and `updateTracker` changed their initial `boundingBox` related argument types from `double` to `int`.
29+
- This is because the C++ types changed from `Rect2d` to `Rect` (which is `Rect2i`), for example:
30+
- [3.4](https://docs.opencv.org/3.4/d0/d0a/classcv_1_1Tracker.html#a549159bd0553e6a8de356f3866df1f18)
31+
- [4.8](https://docs.opencv.org/4.8.0/d0/d0a/classcv_1_1Tracker.html#a92d2012f576e6c06eb2e257d110a6529)
32+
- For example, `IsRect rect C.CDouble` to `IsRect rect Int32`.
33+
- The `TrackerFeatureType` was extended to have the `FEATURE2D` constructor carry 2 `String` fields `detectorType` and `descriptorType`.
34+
The previous argument-less type did not really make sense, as one cannot construct a `Feature2d` tracker feature without specifying these.
35+
This was possible in the previous OpenCV 3 API only because its docs said `The modes available now: "HAAR"` and for all other types, including `Feature2d`, it said `The modes that will be available soon`, so that likely never worked.
36+
This change should allow to use the many more feature types from [`Feature2D`](https://docs.opencv.org/4.8.0/d0/d13/classcv_1_1Feature2D.html).
537
- Support versions of Glob < 0.9.
638

739

opencv-extra/include/tracking.hpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
#ifndef __HASKELL_OPENCV_TRACKING_H__
22
#define __HASKELL_OPENCV_TRACKING_H__
33

4+
#include <opencv2/video/detail/tracking.detail.hpp>
5+
#include <opencv2/tracking/tracking_legacy.hpp>
6+
47
typedef cv::Ptr<cv::Tracker> Ptr_Tracker;
5-
typedef cv::Ptr<cv::TrackerFeature> Ptr_TrackerFeature;
6-
typedef cv::Ptr<cv::MultiTracker> Ptr_MultiTracker;
7-
typedef cv::Ptr<cv::MultiTracker_Alt> Ptr_MultiTrackerAlt;
8+
typedef cv::Ptr<cv::detail::tracking::TrackerFeature> Ptr_TrackerFeature;
9+
typedef cv::Ptr<cv::legacy::tracking::MultiTracker> Ptr_MultiTracker;
10+
typedef cv::Ptr<cv::legacy::tracking::MultiTracker_Alt> Ptr_MultiTrackerAlt;
811

912
#endif /* __HASKELL_OPENCV_TRACKING_H__ */
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
#ifndef __OPENCV_XFEATURES_SIFT_H__
22
#define __OPENCV_XFEATURES_SIFT_H__
33

4+
// Note that `opencv2/xfeatures2d.hpp` does not exist in many OpenCV installations
5+
// because it requires the `OPENCV_ENABLE_NONFREE` option (SIFT and SURF are patented).
46
#include "opencv2/xfeatures2d.hpp"
57

68
/*
79
This file defines some SIFT related names that are used in
810
9-
src/OpenCV/XFeatures2d.hsc.
11+
src/OpenCV/XFeatures2d.hs.
1012
1113
The reason we need these names is that we can't directly reference their
1214
definitions because that would result in invalid syntax in either hsc2hs and
1315
inline-c.
1416
*/
1517

16-
typedef cv::Ptr<cv::xfeatures2d::SIFT> Ptr_SIFT;
18+
typedef cv::Ptr<cv::SIFT> Ptr_SIFT;
1719

1820
#endif /* __OPENCV_XFEATURES_SIFT_H__ */

opencv-extra/include/xfeatures/surf.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
#ifndef __OPENCV_XFEATURES_SURF_H__
22
#define __OPENCV_XFEATURES_SURF_H__
33

4+
// Note that `opencv2/xfeatures2d.hpp` does not exist in many OpenCV installations
5+
// because it requires the `OPENCV_ENABLE_NONFREE` option (SIFT and SURF are patented).
46
#include "opencv2/xfeatures2d.hpp"
57

68
/*
79
This file defines some SURF related names that are used in
810
9-
src/OpenCV/XFeatures2d.hsc.
11+
src/OpenCV/XFeatures2d.hs.
1012
1113
The reason we need these names is that we can't directly reference their
1214
definitions because that would result in invalid syntax in either hsc2hs and

opencv-extra/opencv-extra.cabal

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ source-repository head
4040

4141
flag opencv4
4242
description: Use OpenCV >= 4.0.0
43+
default: True
44+
manual: True
45+
46+
flag enable-nonfree
47+
description: Builds modules that only work if the system OpenCV was built with the OPENCV_ENABLE_NONFREE option (most OpenCV installations lack this by default).
4348
default: False
4449
manual: True
4550

@@ -102,7 +107,6 @@ library
102107
OpenCV.Extra
103108
OpenCV.Extra.ArUco
104109
OpenCV.Extra.Bgsegm
105-
OpenCV.Extra.XFeatures2d
106110
OpenCV.Extra.Tracking
107111
OpenCV.Extra.XImgProc
108112
OpenCV.Extra.XPhoto
@@ -112,6 +116,12 @@ library
112116
OpenCV.Extra.Internal.C.Types
113117
OpenCV.Extra.Internal.XImgProc.Constants
114118

119+
if flag(enable-nonfree)
120+
exposed-modules:
121+
OpenCV.Extra.XFeatures2d
122+
ghc-options:
123+
-DHASKELL_OPENCV_ENABLE_NONFREE
124+
115125
default-extensions:
116126
BangPatterns
117127
DataKinds

opencv-extra/src/OpenCV/Extra.hs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# LANGUAGE CPP #-}
12
{-# OPTIONS_GHC -fno-warn-dodgy-exports #-}
23

34
module OpenCV.Extra
@@ -7,7 +8,10 @@ module OpenCV.Extra
78
import OpenCV.Extra.ArUco as Extra
89
import OpenCV.Extra.Bgsegm as Extra
910
import OpenCV.Extra.Tracking as Extra
10-
import OpenCV.Extra.XFeatures2d as Extra
1111
import OpenCV.Extra.XImgProc as Extra
1212
import OpenCV.Extra.XPhoto as Extra
1313
import OpenCV.Extra.XPhoto.WhiteBalancer as Extra
14+
15+
#if HASKELL_OPENCV_ENABLE_NONFREE
16+
import OpenCV.Extra.XFeatures2d as Extra
17+
#endif

opencv-extra/src/OpenCV/Extra/ArUco.hsc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ C.context openCvExtraCtx
6363

6464
C.include "opencv2/aruco.hpp"
6565
C.include "opencv2/aruco/charuco.hpp"
66+
C.include "opencv2/calib3d.hpp"
6667
C.include "opencv2/core.hpp"
6768
C.include "iostream"
6869
C.include "aruco.hpp"
@@ -254,7 +255,7 @@ drawEstimatedPose cameraMatrix distCoeffs (rvec, tvec) image = unsafePrimToPrim
254255
withPtr rvec $ \rvecPtr ->
255256
withPtr tvec $ \tvecPtr ->
256257
[C.block| void {
257-
drawAxis
258+
drawFrameAxes
258259
( *$(Mat * imagePtr)
259260
, *$(Matx33d * c'cameraMatrix)
260261
, *$(Matx51d * c'distCoeffs)

opencv-extra/src/OpenCV/Extra/Tracking.hs

Lines changed: 54 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ module OpenCV.Extra.Tracking
2424
) where
2525

2626
import "base" Data.Word
27+
import "base" Data.Int (Int32)
2728
import "base" Foreign.ForeignPtr ( ForeignPtr, withForeignPtr )
2829
import "base" Foreign.C.String ( withCString )
2930
import "base" Foreign.Marshal.Utils ( toBool )
@@ -45,6 +46,7 @@ C.context openCvExtraCtx
4546

4647
C.include "opencv2/core.hpp"
4748
C.include "opencv2/tracking.hpp"
49+
C.include "opencv2/tracking/tracking_legacy.hpp"
4850

4951
C.include "tracking.hpp"
5052

@@ -53,20 +55,22 @@ C.using "namespace cv"
5355
--------------------------------------------------------------------------------
5456

5557
data TrackerType
56-
= BOOSTING -- ^
57-
| MIL -- ^
58+
= MIL -- ^
5859
| KCF -- ^
59-
| MEDIANFLOW -- ^
60-
| TLD -- ^
6160
| GOTURN -- ^
6261
deriving (Eq, Show, Enum, Bounded)
6362

63+
type FEATURE2D_DetectorType = String
64+
type FEATURE2D_DescriptorType = String
65+
6466
data TrackerFeatureType
6567
= HAAR -- ^ Haar Feature-based
66-
| HOG -- ^ soon Histogram of Oriented Gradients features
67-
| LBP -- ^ soon Local Binary Pattern features
68-
| FEATURE2D -- ^ soon All types of Feature2D
69-
deriving (Eq, Show, Enum, Bounded)
68+
| HOG -- ^ Histogram of Oriented Gradients features
69+
| LBP -- ^ Local Binary Pattern features
70+
| FEATURE2D -- ^ All types of Feature2D
71+
FEATURE2D_DetectorType
72+
FEATURE2D_DescriptorType
73+
deriving (Eq, Show)
7074

7175
--------------------------------------------------------------------------------
7276

@@ -87,27 +91,24 @@ newTracker
8791
-- ^ Name
8892
-> m (Tracker (PrimState m))
8993
newTracker tType = unsafePrimToPrim $ fromPtr $ case tType of
90-
BOOSTING -> [CU.block|Ptr_Tracker * {return new cv::Ptr<cv::Tracker>(cv::TrackerBoosting::create());}|]
9194
MIL -> [CU.block|Ptr_Tracker * {return new cv::Ptr<cv::Tracker>(cv::TrackerMIL::create());}|]
9295
KCF -> [CU.block|Ptr_Tracker * {return new cv::Ptr<cv::Tracker>(cv::TrackerKCF::create());}|]
93-
MEDIANFLOW -> [CU.block|Ptr_Tracker * {return new cv::Ptr<cv::Tracker>(cv::TrackerMedianFlow::create());}|]
94-
TLD -> [CU.block|Ptr_Tracker * {return new cv::Ptr<cv::Tracker>(cv::TrackerTLD::create());}|]
9596
GOTURN -> [CU.block|Ptr_Tracker * {return new cv::Ptr<cv::Tracker>(cv::TrackerGOTURN::create());}|]
9697

9798
initTracker
98-
:: (PrimMonad m, IsRect rect C.CDouble)
99+
:: (PrimMonad m, IsRect rect Int32)
99100
=> Tracker (PrimState m)
100101
-> Mat ('S '[ 'D, 'D]) ('D) ('D)
101-
-> rect C.CDouble
102-
-> m Bool
102+
-> rect Int32
103+
-> m ()
103104
initTracker trk srcImg boundingBox = unsafePrimToPrim $
104105
withPtr trk $ \trkPtr ->
105106
withPtr srcImg $ \srcPtr ->
106-
withPtr (toRect boundingBox) $ \rectPtr -> toBool <$>
107-
[C.block| bool {
108-
return (*$(Ptr_Tracker * trkPtr))->init
107+
withPtr (toRect boundingBox) $ \rectPtr ->
108+
[C.block| void {
109+
(*$(Ptr_Tracker * trkPtr))->init
109110
( *$(Mat * srcPtr)
110-
, *$(Rect2d * rectPtr)
111+
, *$(const Rect2i * rectPtr)
111112
);
112113
}
113114
|]
@@ -116,22 +117,23 @@ updateTracker
116117
:: (PrimMonad m)
117118
=> Tracker (PrimState m)
118119
-> Mat ('D) ('D) ('S Word8)
119-
-> m (Maybe (Rect C.CDouble))
120-
-- -> m (Maybe (Rect Int32))
120+
-> m (Maybe (Rect Int32))
121121
updateTracker trk srcImg = unsafePrimToPrim $
122122
withPtr trk $ \trkPtr ->
123123
withPtr srcImg $ \srcPtr ->
124124
withPtr rect $ \rectPtr -> do
125125
ok <- toBool <$> [C.block| bool {
126-
return (*$(Ptr_Tracker * trkPtr))->update
126+
Rect2i boundingBox = *$(Rect2i * rectPtr);
127+
return (*$(Ptr_Tracker * trkPtr))->update
127128
( *$(Mat * srcPtr)
128-
, *$(Rect2d * rectPtr)
129+
// , *$(Rect2i * rectPtr)
130+
, boundingBox
129131
);
130132
}
131133
|]
132134
pure $ if ok then Just rect else Nothing
133135
where
134-
rect :: Rect2d
136+
rect :: Rect2i
135137
rect = toRect HRect{hRectTopLeft = 0, hRectSize = 0}
136138

137139
--------------------------------------------------------------------------------
@@ -144,9 +146,9 @@ type instance C (TrackerFeature s) = C'Ptr_TrackerFeature
144146
type instance C (MultiTracker s) = C'Ptr_MultiTracker
145147
type instance C (MultiTrackerAlt s) = C'Ptr_MultiTrackerAlt
146148

147-
mkFinalizer ReleaseDeletePtr "deleteTrackerFeature" "cv::Ptr<cv::TrackerFeature>" ''C'Ptr_TrackerFeature
148-
mkFinalizer ReleaseDeletePtr "deleteMultiTracker" "cv::Ptr<cv::MultiTracker>" ''C'Ptr_MultiTracker
149-
mkFinalizer ReleaseDeletePtr "deleteMultiTrackerAlt" "cv::Ptr<cv::MultiTracker_Alt>" ''C'Ptr_MultiTrackerAlt
149+
mkFinalizer ReleaseDeletePtr "deleteTrackerFeature" "cv::Ptr<cv::detail::tracking::TrackerFeature>" ''C'Ptr_TrackerFeature
150+
mkFinalizer ReleaseDeletePtr "deleteMultiTracker" "cv::Ptr<cv::legacy::tracking::MultiTracker>" ''C'Ptr_MultiTracker
151+
mkFinalizer ReleaseDeletePtr "deleteMultiTrackerAlt" "cv::Ptr<cv::legacy::tracking::MultiTracker_Alt>" ''C'Ptr_MultiTrackerAlt
150152

151153
instance WithPtr (TrackerFeature s) where
152154
withPtr = withForeignPtr . unTrackerFeature
@@ -174,7 +176,7 @@ newMultiTracker
174176
newMultiTracker =
175177
unsafePrimToPrim $ fromPtr $
176178
[CU.block|Ptr_MultiTracker * {
177-
return new cv::Ptr<cv::MultiTracker>(new cv::MultiTracker());
179+
return new cv::Ptr<cv::legacy::tracking::MultiTracker>(new cv::legacy::tracking::MultiTracker());
178180
}|]
179181

180182
--------------------------------------------------------------------------------
@@ -184,10 +186,28 @@ newTrackerFeature
184186
=> TrackerFeatureType -- ^ Name
185187
-> m (TrackerFeature (PrimState m))
186188
newTrackerFeature trackerFeatureType =
187-
unsafePrimToPrim $ fromPtr $
188-
withCString (show trackerFeatureType) $ \c'trackerFeatureType ->
189-
[CU.block|Ptr_TrackerFeature * {
190-
cv::Ptr<cv::TrackerFeature> ftracker =
191-
cv::TrackerFeature::create(cv::String($(const char * c'trackerFeatureType)));
192-
return new cv::Ptr<cv::TrackerFeature>(ftracker);
193-
}|]
189+
unsafePrimToPrim $ fromPtr $ case trackerFeatureType of
190+
HAAR ->
191+
[CU.block|Ptr_TrackerFeature * {
192+
return new cv::Ptr<cv::detail::tracking::TrackerFeature>(new cv::detail::tracking::TrackerContribFeatureHAAR());
193+
}|]
194+
HOG ->
195+
[CU.block|Ptr_TrackerFeature * {
196+
return new cv::Ptr<cv::detail::tracking::TrackerFeature>(new cv::detail::tracking::TrackerFeatureHOG());
197+
}|]
198+
LBP ->
199+
[CU.block|Ptr_TrackerFeature * {
200+
return new cv::Ptr<cv::detail::tracking::TrackerFeature>(new cv::detail::tracking::TrackerFeatureLBP());
201+
}|]
202+
FEATURE2D detectorType descriptorType ->
203+
withCString (show detectorType) $ \c'detectorType ->
204+
withCString (show descriptorType) $ \c'descriptorType ->
205+
206+
[CU.block|Ptr_TrackerFeature * {
207+
return new cv::Ptr<cv::detail::tracking::TrackerFeature>(
208+
new cv::detail::tracking::TrackerFeatureFeature2d(
209+
cv::String($(const char * c'detectorType)),
210+
cv::String($(const char * c'descriptorType))
211+
)
212+
);
213+
}|]

0 commit comments

Comments
 (0)