Skip to content

Commit a710151

Browse files
committed
overloaded approxPolyDP
Also handle exceptions.
1 parent 20ca161 commit a710151

File tree

2 files changed

+164
-106
lines changed

2 files changed

+164
-106
lines changed

opencv/src/OpenCV/ImgProc/StructuralAnalysis.hsc

+6-66
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@ module OpenCV.ImgProc.StructuralAnalysis
77
, ContourRetrievalMode(..)
88
, ContourApproximationMethod(..)
99

10-
, approxPolyDP
10+
, approxPolyDP, ApproxPolyDP
1111
, arcLength
1212
, boundingRect
1313
, contourArea
14-
, ConvexHull
15-
, convexHull
14+
, convexHull, ConvexHull
1615
, findContours
1716
, isContourConvex
1817
, minAreaRect
@@ -47,7 +46,7 @@ import "this" OpenCV.Internal.C.Types
4746
import "this" OpenCV.Internal.Core.Types
4847
import "this" OpenCV.Internal.Core.Types.Mat
4948
import "this" OpenCV.Internal.Exception
50-
import "this" OpenCV.Internal.ImgProc.StructuralAnalysis ( ConvexHull, convexHull )
49+
import "this" OpenCV.Internal.ImgProc.StructuralAnalysis
5150
import "this" OpenCV.TypeLevel
5251
import qualified "vector" Data.Vector as V
5352

@@ -133,65 +132,6 @@ data Contour
133132
, contourChildren :: !(V.Vector Contour)
134133
} deriving Show
135134

136-
{- | Approximates a polygonal curve(s) with the specified precision.
137-
138-
The functions approxPolyDP approximate a curve or a polygon with another
139-
curve/polygon with less vertices so that the distance between them is less or
140-
equal to the specified precision. It uses the
141-
<http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm Douglas-Peucker algorithm>
142-
143-
<http://docs.opencv.org/3.0-last-rst/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=contourarea#approxpolydp>
144-
-}
145-
approxPolyDP
146-
:: (IsPoint2 point2 Int32)
147-
=> V.Vector (point2 Int32)
148-
-> Double -- ^ epsilon
149-
-> Bool -- ^ is closed
150-
-> V.Vector Point2i -- vector of points
151-
approxPolyDP curve epsilon isClosed = unsafePerformIO $
152-
withArrayPtr (V.map toPoint curve) $ \curvePtr ->
153-
alloca $ \(pointsResPtrPtr ::Ptr (Ptr (Ptr C'Point2i))) ->
154-
alloca $ \(numPointsResPtr :: Ptr Int32) -> mask_ $ do
155-
[C.block| void {
156-
std::vector<cv::Point> points_res;
157-
cv::_InputArray curve = cv::_InputArray ($(Point2i * curvePtr), $(int32_t c'numPoints));
158-
cv::approxPolyDP
159-
( curve
160-
, points_res
161-
, $(double c'epsilon)
162-
, $(bool c'isClosed)
163-
);
164-
165-
*$(int32_t * numPointsResPtr) = points_res.size();
166-
167-
cv::Point * * * pointsResPtrPtr = $(Point2i * * * pointsResPtrPtr);
168-
cv::Point * * pointsResPtr = new cv::Point * [points_res.size()];
169-
*pointsResPtrPtr = pointsResPtr;
170-
171-
for (std::vector<cv::Point>::size_type i = 0; i < points_res.size(); i++) {
172-
cv::Point & ptAddress = points_res[i];
173-
cv::Point * newPt = new cv::Point(ptAddress.x, ptAddress.y);
174-
pointsResPtr[i] = newPt;
175-
}
176-
}|]
177-
178-
numPoints <- fromIntegral <$> peek numPointsResPtr
179-
180-
pointsResPtr <- peek pointsResPtrPtr
181-
(pointsResList :: [Point2i]) <- peekArray numPoints pointsResPtr >>= mapM (fromPtr . pure) --CHECK THIS
182-
let pointsRes :: V.Vector (Point2i)
183-
pointsRes = V.fromList pointsResList
184-
185-
[CU.block| void {
186-
delete [] *$(Point2i * * * pointsResPtrPtr);
187-
} |]
188-
189-
return pointsRes
190-
where
191-
c'numPoints = fromIntegral $ V.length curve
192-
c'isClosed = fromBool isClosed
193-
c'epsilon = realToFrac epsilon
194-
195135
arcLength
196136
:: (IsPoint2 point2 Int32)
197137
=> V.Vector (point2 Int32)
@@ -204,16 +144,16 @@ arcLength curve isClosed = unsafeWrapException $
204144
[cvExcept|
205145
cv::_InputArray curve =
206146
cv::_InputArray ( $(Point2i * curvePtr)
207-
, $(int32_t c'numPoints)
147+
, $(int32_t c'numCurvePoints)
208148
);
209149
*$(double * c'resultPtr) =
210150
cv::arcLength( curve
211-
, $(bool c'isClosed)
151+
, $(bool c'isClosed)
212152
);
213153
|]
214154
where
215155
c'isClosed = fromBool isClosed
216-
c'numPoints = fromIntegral $ V.length curve
156+
c'numCurvePoints = fromIntegral $ V.length curve
217157

218158
{- | Calculates the up-right bounding rectangle of a point set.
219159

opencv/src/OpenCV/Internal/ImgProc/StructuralAnalysis.hs

+158-40
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
#endif
88

99
module OpenCV.Internal.ImgProc.StructuralAnalysis
10-
( convexHull
10+
( approxPolyDP
11+
, ApproxPolyDP(..)
12+
, convexHull
1113
, ConvexHull(..)
1214
) where
1315

@@ -39,6 +41,129 @@ C.using "namespace cv"
3941

4042
--------------------------------------------------------------------------------
4143

44+
45+
{- | Approximates a polygonal curve(s) with the specified precision.
46+
47+
The functions approxPolyDP approximate a curve or a polygon with another
48+
curve/polygon with less vertices so that the distance between them is less or
49+
equal to the specified precision. It uses the
50+
<http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm Douglas-Peucker algorithm>
51+
52+
<http://docs.opencv.org/3.0-last-rst/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=contourarea#approxpolydp>
53+
-}
54+
approxPolyDP
55+
:: forall point2 depth
56+
. ( IsPoint2 point2 depth
57+
, ApproxPolyDP depth
58+
)
59+
=> V.Vector (point2 depth)
60+
-> Double -- ^ epsilon
61+
-> Bool -- ^ is closed
62+
-> CvExcept (V.Vector (Point 2 depth))
63+
approxPolyDP curve epsilon isClosed = unsafeWrapException $
64+
withArrayPtr (V.map toPoint curve) $ \curvePtr ->
65+
alloca $ \(approxPtrPtr :: Ptr (Ptr (Ptr (C (Point 2 depth))))) ->
66+
alloca $ \(approxSizePtr :: Ptr Int32) ->
67+
handleCvException
68+
( do approxSize <- fromIntegral <$> peek approxSizePtr
69+
approxPtr :: Ptr (Ptr (C (Point 2 depth))) <- peek approxPtrPtr
70+
approxList :: [Ptr (C (Point 2 depth))] <- peekArray approxSize approxPtr
71+
approxVec <- V.fromList <$> mapM (fromPtr . pure) approxList
72+
approxPolyDP_deletePtrArray approxPtrPtr
73+
pure approxVec
74+
) $
75+
approxPolyDP_internal
76+
(fromIntegral $ V.length curve)
77+
curvePtr
78+
approxSizePtr
79+
approxPtrPtr
80+
(toCDouble epsilon)
81+
(fromBool isClosed)
82+
83+
-- | Internal class used to overload the 'approxPolyDP' depth.
84+
class ( FromPtr (Point 2 depth)
85+
, CSizeOf (C'Point 2 depth)
86+
, PlacementNew (C'Point 2 depth)
87+
) => ApproxPolyDP depth where
88+
approxPolyDP_internal
89+
:: Int32 -- ^ Number of input curve points.
90+
-> Ptr (C (Point 2 depth)) -- ^ Input curve points array.
91+
-> Ptr Int32 -- ^ Size of approximated curve.
92+
-> Ptr (Ptr (Ptr (C (Point 2 depth))))
93+
-- ^ Array of pointers to approximated curve points.
94+
-> CDouble -- ^ epsilon
95+
-> CInt -- ^ is closed
96+
-> IO (Ptr (C CvCppException))
97+
98+
approxPolyDP_deletePtrArray
99+
:: Ptr (Ptr (Ptr (C (Point 2 depth))))
100+
-- ^ Array of pointers to approximated curve points.
101+
-> IO ()
102+
103+
instance ApproxPolyDP Int32 where
104+
approxPolyDP_internal curveSize curvePtr approxSizePtr approxPtrPtr epsilon isClosed =
105+
[cvExcept|
106+
cv::_InputArray curve =
107+
cv::_InputArray( $(Point2i * curvePtr)
108+
, $(int32_t curveSize)
109+
);
110+
std::vector<cv::Point2i> approx;
111+
cv::approxPolyDP
112+
( curve
113+
, approx
114+
, $(double epsilon)
115+
, $(bool isClosed)
116+
);
117+
118+
*$(int32_t * approxSizePtr) = approx.size();
119+
120+
cv::Point2i * * * approxPtrPtr = $(Point2i * * * approxPtrPtr);
121+
cv::Point2i * * approxPtr = new cv::Point2i * [approx.size()];
122+
*approxPtrPtr = approxPtr;
123+
124+
for (std::vector<cv::Point2i>::size_type i = 0; i < approx.size(); i++) {
125+
cv::Point2i & ptAddress = approx[i];
126+
cv::Point2i * newPt = new cv::Point2i(ptAddress.x, ptAddress.y);
127+
approxPtr[i] = newPt;
128+
}
129+
|]
130+
131+
approxPolyDP_deletePtrArray approxPtrPtr =
132+
[CU.block| void { delete [] *$(Point2i * * * approxPtrPtr); } |]
133+
134+
instance ApproxPolyDP CFloat where
135+
approxPolyDP_internal curveSize curvePtr approxSizePtr approxPtrPtr epsilon isClosed =
136+
[cvExcept|
137+
cv::_InputArray curve =
138+
cv::_InputArray( $(Point2f * curvePtr)
139+
, $(int32_t curveSize)
140+
);
141+
std::vector<cv::Point2f> approx;
142+
cv::approxPolyDP
143+
( curve
144+
, approx
145+
, $(double epsilon)
146+
, $(bool isClosed)
147+
);
148+
149+
*$(int32_t * approxSizePtr) = approx.size();
150+
151+
cv::Point2f * * * approxPtrPtr = $(Point2f * * * approxPtrPtr);
152+
cv::Point2f * * approxPtr = new cv::Point2f * [approx.size()];
153+
*approxPtrPtr = approxPtr;
154+
155+
for (std::vector<cv::Point2f>::size_type i = 0; i < approx.size(); i++) {
156+
cv::Point2f & ptAddress = approx[i];
157+
cv::Point2f * newPt = new cv::Point2f(ptAddress.x, ptAddress.y);
158+
approxPtr[i] = newPt;
159+
}
160+
|]
161+
162+
approxPolyDP_deletePtrArray approxPtrPtr =
163+
[CU.block| void { delete [] *$(Point2f * * * approxPtrPtr); } |]
164+
165+
--------------------------------------------------------------------------------
166+
42167
{- | Finds the convex hull of a point set.
43168
44169
Finds the convex hull of a 2D point set using the Sklansky's algorithm
@@ -61,103 +186,96 @@ convexHull
61186
convexHull points clockwise = unsafeWrapException $
62187
withArrayPtr (V.map toPoint points) $ \(pointsPtr :: Ptr (C (Point 2 depth))) ->
63188
alloca $ \(hullPointsPtrPtr :: Ptr (Ptr (Ptr (C (Point 2 depth))))) ->
64-
alloca $ \(numHullPointsPtr :: Ptr Int32) ->
189+
alloca $ \(hullSizePtr :: Ptr Int32) ->
65190
handleCvException
66-
( do numHullPoints <- fromIntegral <$> peek numHullPointsPtr
191+
( do hullSize <- fromIntegral <$> peek hullSizePtr
67192
hullPointsPtr :: Ptr (Ptr (C (Point 2 depth))) <- peek hullPointsPtrPtr
68-
hullPointsList :: [Ptr (C (Point 2 depth))] <- peekArray numHullPoints hullPointsPtr
193+
hullPointsList :: [Ptr (C (Point 2 depth))] <- peekArray hullSize hullPointsPtr
69194
hullPointsVec <- V.fromList <$> mapM (fromPtr . pure) hullPointsList
70195
convexHull_deletePtrArray hullPointsPtrPtr
71196
pure hullPointsVec
72197
) $
73198
convexHull_internal
74199
(fromIntegral $ V.length points)
75-
(fromBool clockwise)
76200
pointsPtr
201+
(fromBool clockwise)
77202
hullPointsPtrPtr
78-
numHullPointsPtr
203+
hullSizePtr
79204

80205
-- | Internal class used to overload the 'convexHull' depth.
81206
class ( FromPtr (Point 2 depth)
82207
, CSizeOf (C'Point 2 depth)
83208
, PlacementNew (C'Point 2 depth)
84209
) => ConvexHull depth where
85210
convexHull_internal
86-
:: Int32
87-
-> CInt
88-
-> Ptr (C (Point 2 depth))
211+
:: Int32 -- ^ Number of input points.
212+
-> Ptr (C (Point 2 depth)) -- ^ Input points array.
213+
-> CInt -- ^ Orientation flag.
89214
-> Ptr (Ptr (Ptr (C (Point 2 depth))))
90-
-> Ptr Int32
215+
-- ^ Array of pointers to hull points.
216+
-> Ptr Int32 -- ^ Size of convex hull.
91217
-> IO (Ptr (C CvCppException))
92218

93219
convexHull_deletePtrArray
94220
:: Ptr (Ptr (Ptr (C (Point 2 depth))))
221+
-- ^ Array of pointers to hull points.
95222
-> IO ()
96223

97-
instance ConvexHull CFloat where
98-
convexHull_internal numPoints clockwise pointsPtr hullPointsPtrPtr numHullPointsPtr =
224+
instance ConvexHull Int32 where
225+
convexHull_internal numPoints pointsPtr clockwise hullPointsPtrPtr hullSizePtr =
99226
[cvExcept|
100227
cv::_InputArray points =
101-
cv::_InputArray( $(Point2f * pointsPtr)
228+
cv::_InputArray( $(Point2i * pointsPtr)
102229
, $(int32_t numPoints)
103230
);
104-
std::vector<cv::Point2f> hull;
231+
std::vector<cv::Point2i> hull;
105232
cv::convexHull
106233
( points
107234
, hull
108235
, $(bool clockwise)
109236
, true
110237
);
111238

112-
*$(int32_t * numHullPointsPtr) = hull.size();
239+
*$(int32_t * hullSizePtr) = hull.size();
113240

114-
cv::Point2f * * * hullPointsPtrPtr = $(Point2f * * * hullPointsPtrPtr);
115-
cv::Point2f * * hullPointsPtr = new cv::Point2f * [hull.size()];
241+
cv::Point2i * * * hullPointsPtrPtr = $(Point2i * * * hullPointsPtrPtr);
242+
cv::Point2i * * hullPointsPtr = new cv::Point2i * [hull.size()];
116243
*hullPointsPtrPtr = hullPointsPtr;
117244

118245
for (std::vector<cv::Point2i>::size_type i = 0; i < hull.size(); i++)
119246
{
120-
cv::Point2f & hullPt = hull[i];
121-
cv::Point2f * newHullPt = new cv::Point2f(hullPt.x, hullPt.y);
247+
cv::Point2i & hullPt = hull[i];
248+
cv::Point2i * newHullPt = new cv::Point2i(hullPt.x, hullPt.y);
122249
hullPointsPtr[i] = newHullPt;
123250
}
124251
|]
125252

126253
convexHull_deletePtrArray hullPointsPtrPtr =
127-
[CU.block| void {
128-
delete [] *$(Point2f * * * hullPointsPtrPtr);
129-
}|]
254+
[CU.block| void { delete [] *$(Point2i * * * hullPointsPtrPtr); }|]
130255

131-
instance ConvexHull Int32 where
132-
convexHull_internal numPoints clockwise pointsPtr hullPointsPtrPtr numHullPointsPtr =
256+
instance ConvexHull CFloat where
257+
convexHull_internal numPoints pointsPtr clockwise hullPointsPtrPtr hullSizePtr =
133258
[cvExcept|
134259
cv::_InputArray points =
135-
cv::_InputArray( $(Point2i * pointsPtr)
260+
cv::_InputArray( $(Point2f * pointsPtr)
136261
, $(int32_t numPoints)
137262
);
138-
std::vector<cv::Point2i> hull;
139-
cv::convexHull
140-
( points
141-
, hull
142-
, $(bool clockwise)
143-
, true
144-
);
263+
std::vector<cv::Point2f> hull;
264+
cv::convexHull(points, hull, $(bool clockwise), true);
145265

146-
*$(int32_t * numHullPointsPtr) = hull.size();
266+
*$(int32_t * hullSizePtr) = hull.size();
147267

148-
cv::Point2i * * * hullPointsPtrPtr = $(Point2i * * * hullPointsPtrPtr);
149-
cv::Point2i * * hullPointsPtr = new cv::Point2i * [hull.size()];
268+
cv::Point2f * * * hullPointsPtrPtr = $(Point2f * * * hullPointsPtrPtr);
269+
cv::Point2f * * hullPointsPtr = new cv::Point2f * [hull.size()];
150270
*hullPointsPtrPtr = hullPointsPtr;
151271

152272
for (std::vector<cv::Point2i>::size_type i = 0; i < hull.size(); i++)
153273
{
154-
cv::Point2i & hullPt = hull[i];
155-
cv::Point2i * newHullPt = new cv::Point2i(hullPt.x, hullPt.y);
274+
cv::Point2f & hullPt = hull[i];
275+
cv::Point2f * newHullPt = new cv::Point2f(hullPt.x, hullPt.y);
156276
hullPointsPtr[i] = newHullPt;
157277
}
158278
|]
159279

160280
convexHull_deletePtrArray hullPointsPtrPtr =
161-
[CU.block| void {
162-
delete [] *$(Point2i * * * hullPointsPtrPtr);
163-
}|]
281+
[CU.block| void { delete [] *$(Point2f * * * hullPointsPtrPtr); }|]

0 commit comments

Comments
 (0)