diff --git a/README.md b/README.md
index 516d5cbc..4fe14442 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,13 @@
-[](https://hackage.haskell.org/package/opencv)
[](https://travis-ci.org/LumiGuide/haskell-opencv)
+[opencv ](https://hackage.haskell.org/package/opencv)
+
+[opencv-extra ](https://hackage.haskell.org/package/opencv-extra)
+
Haskell OpenCV-3.x binding
==========================
-
+
This is a Haskell library providing a binding to OpenCV-3.x. It binds directly
@@ -42,11 +45,11 @@ break between minor releases, so be careful.
Development
-----------
-We use Nix to enter an environment containing all the needed dependencies. For
-the moment the following commands only work on Linux. The Nix expression for
-opencv-extra currently fails to build on OS X.
+To get into an environment that contains all the needed dependencies we use Nix.
+The following commands work both on Linux and OS X:
curl https://nixos.org/nix/install | sh # Only execute this if you haven't installed Nix yet.
+ cd opencv[-extra]
nix-shell
Then you should be able to use `cabal` as normal.
diff --git a/data/haskell-opencv-logo-200x82.png b/data/haskell-opencv-logo-200x82.png
new file mode 100644
index 00000000..ec63774b
Binary files /dev/null and b/data/haskell-opencv-logo-200x82.png differ
diff --git a/nixpkgs-config.nix b/nixpkgs-config.nix
index 351c40fe..2bee0e7c 100644
--- a/nixpkgs-config.nix
+++ b/nixpkgs-config.nix
@@ -15,7 +15,7 @@
opencv3 = pkgs.opencv3.override {
enableIpp = !osx;
- enableContrib = !osx;
+ enableContrib = true;
enableGtk2 = true;
enableFfmpeg = !osx;
enableGStreamer = true;
diff --git a/nixpkgs.nix b/nixpkgs.nix
index 1804c3cf..bfe5c0f0 100644
--- a/nixpkgs.nix
+++ b/nixpkgs.nix
@@ -2,6 +2,6 @@ let pkgs = import {};
in pkgs.fetchFromGitHub {
owner = "NixOS";
repo = "nixpkgs";
- rev = "0011f9065a1ad1da4db67bec8d535d91b0a78fba";
- sha256 = "0m662mibyxqmp83zdhsi084p2h90268h3i8bfk3b2q8pbjz89yx2";
+ rev = "89e02c7516ff301d28301926e9d7b373f29836fe";
+ sha256 = "0v28hyyn1hw9951w1zvq5s40bbmk3gpjsmhq0cyp7lvs7d1aq0z7";
}
diff --git a/opencv-examples/opencv-examples.cabal b/opencv-examples/opencv-examples.cabal
index 350da0f1..e1d8e22f 100644
--- a/opencv-examples/opencv-examples.cabal
+++ b/opencv-examples/opencv-examples.cabal
@@ -14,6 +14,11 @@ extra-source-files:
data/*.jpg
data/*.xml
+source-repository head
+ type: git
+ location: git://github.com/LumiGuide/haskell-opencv.git
+ subdir: opencv-examples
+
library
hs-source-dirs: lib
exposed-modules:
diff --git a/opencv-extra-examples/opencv-extra-examples.cabal b/opencv-extra-examples/opencv-extra-examples.cabal
index cd1ace4e..40e0469c 100644
--- a/opencv-extra-examples/opencv-extra-examples.cabal
+++ b/opencv-extra-examples/opencv-extra-examples.cabal
@@ -13,6 +13,11 @@ extra-source-files:
data/*.jpg
data/*.xml
+source-repository head
+ type: git
+ location: git://github.com/LumiGuide/haskell-opencv.git
+ subdir: opencv-extra-examples
+
executable tracker
main-is: tracker.hs
hs-source-dirs: src
diff --git a/opencv-extra/CHANGELOG.md b/opencv-extra/CHANGELOG.md
new file mode 100644
index 00000000..e2e5c7b2
--- /dev/null
+++ b/opencv-extra/CHANGELOG.md
@@ -0,0 +1,14 @@
+## [0.0.0.1] - 2017-06-20
+
+### Changed
+
+- Fix build on OS X.
+- Add source repo to cabal file.
+- Added a Cabal package description.
+
+## 0.0.0.0 - 2017-06-11
+
+- Initial version
+
+
+[0.0.0.1]: https://github.com/LumiGuide/haskell-opencv/compare/opencv-extra-0.0.0.0...opencv-extra-0.0.0.1
diff --git a/opencv-extra/Setup.hs b/opencv-extra/Setup.hs
index 031daa10..6a35c073 100644
--- a/opencv-extra/Setup.hs
+++ b/opencv-extra/Setup.hs
@@ -3,6 +3,6 @@ import System.Environment ( getArgs )
main = do
args <- getArgs
- let args' | "configure" `elem` args = args ++ ["--with-gcc","g++", "--with-ld","g++"]
+ let args' | "configure" `elem` args = args ++ ["--with-gcc","c++", "--with-ld","c++"]
| otherwise = args
defaultMainArgs args'
diff --git a/opencv-extra/opencv-extra.cabal b/opencv-extra/opencv-extra.cabal
index d85eecd0..683d155d 100644
--- a/opencv-extra/opencv-extra.cabal
+++ b/opencv-extra/opencv-extra.cabal
@@ -1,5 +1,5 @@
name: opencv-extra
-version: 0.0.0.0
+version: 0.0.0.1
homepage: https://github.com/LumiGuide/haskell-opencv
bug-reports: https://github.com/LumiGuide/haskell-opencv/issues
license: BSD3
@@ -10,11 +10,29 @@ build-type: Custom
cabal-version: >=1.23
category: AI, Graphics
synopsis: Haskell binding to OpenCV-3.x extra modules
+description: <>
+ .
+ This is a Haskell library providing a binding to the OpenCV-3.x contrib modules.
+ It binds directly with the C++ API using the @inline-c@ Haskell library.
+ .
+ The library is far from complete but the framework is there to easily
+ bind missing functionality.
+ .
+ Make sure to checkout the
+ .
+
+extra-source-files:
+ CHANGELOG.md
extra-doc-files:
doc/generated/*.png
doc/generated/examples/*.png
+source-repository head
+ type: git
+ location: git://github.com/LumiGuide/haskell-opencv.git
+ subdir: opencv-extra
+
flag internal-documentation
description: Enables documentation generation for internal modules.
default: False
diff --git a/opencv-extra/opencv-extra.nix b/opencv-extra/opencv-extra.nix
index 0ec2d714..7f3702b6 100644
--- a/opencv-extra/opencv-extra.nix
+++ b/opencv-extra/opencv-extra.nix
@@ -73,8 +73,8 @@ mkDerivation {
libraryPkgconfigDepends = [ opencv3 ];
configureFlags =
- [ "--with-gcc=g++"
- "--with-ld=g++"
+ [ "--with-gcc=${stdenv.cc}/bin/c++"
+ "--with-ld=${stdenv.cc}/bin/c++"
];
hardeningDisable = [ "bindnow" ];
diff --git a/opencv/CHANGELOG.md b/opencv/CHANGELOG.md
new file mode 100644
index 00000000..0de5468a
--- /dev/null
+++ b/opencv/CHANGELOG.md
@@ -0,0 +1,21 @@
+## [0.0.1.0] - 2017-06-20
+
+### Added
+
+- OpenCV.Calib3d: findHomography.
+- OpenCV.Core.ArrayOps: hconcat, vconcat.
+- include/hsc_macros.hpp: #alignof macro.
+
+### Changed
+
+- Fix build on OS X.
+- Add source repo to cabal file.
+- Reference opencv-extra and the examples from the Cabal package description.
+
+
+## 0.0.0.0 - 2017-06-11
+
+- Initial version
+
+
+[0.0.1.0]: https://github.com/LumiGuide/haskell-opencv/compare/opencv-0.0.0.0...opencv-0.0.1.0
diff --git a/opencv/Setup.hs b/opencv/Setup.hs
index 031daa10..6a35c073 100644
--- a/opencv/Setup.hs
+++ b/opencv/Setup.hs
@@ -3,6 +3,6 @@ import System.Environment ( getArgs )
main = do
args <- getArgs
- let args' | "configure" `elem` args = args ++ ["--with-gcc","g++", "--with-ld","g++"]
+ let args' | "configure" `elem` args = args ++ ["--with-gcc","c++", "--with-ld","c++"]
| otherwise = args
defaultMainArgs args'
diff --git a/opencv/include/hsc_macros.hpp b/opencv/include/hsc_macros.hpp
index 1d6e5982..22d71c3f 100644
--- a/opencv/include/hsc_macros.hpp
+++ b/opencv/include/hsc_macros.hpp
@@ -10,6 +10,8 @@ This files defines some hsc2hs macros. For documentation on how to construct cus
#define bc_sizeof_varid(name) {printf("c'sizeof_");bc_word(name);}; \
+#define bc_alignof_varid(name) {printf("c'alignof_");bc_word(name);}; \
+
/*
The #sizeof macro outputs a Haskell constant with the size of the C/C++ type in bytes.
@@ -27,4 +29,23 @@ Results in the following Haskell code:
bc_sizeof_varid(# name);printf(" = %lu\n", sizeof(name)); \
}; \
+/*
+The #alignof macro outputs a Haskell constant with the alignment off the C/C++ type in bytes.
+
+For example the following:
+
+ #alignof Point2i
+
+Results in the following Haskell code:
+
+ c'alignof_Point2i :: Int
+ c'alignof_Point2i = 4
+
+The specific alignment that is calculated is platform dependent.
+*/
+#define hsc_alignof(name) \
+ { bc_alignof_varid(# name);printf(" :: Int\n"); \
+ bc_alignof_varid(# name);printf(" = %lu\n", alignof(name)); \
+ }; \
+
#endif /* __HSC_MACROS_H__ */
diff --git a/opencv/opencv.cabal b/opencv/opencv.cabal
index 708d67e3..4a272a95 100644
--- a/opencv/opencv.cabal
+++ b/opencv/opencv.cabal
@@ -1,5 +1,5 @@
name: opencv
-version: 0.0.0.0
+version: 0.0.1.0
homepage: https://github.com/LumiGuide/haskell-opencv
bug-reports: https://github.com/LumiGuide/haskell-opencv/issues
license: BSD3
@@ -10,13 +10,22 @@ build-type: Custom
cabal-version: >=1.23
category: AI, Graphics
synopsis: Haskell binding to OpenCV-3.x
-description: This is a Haskell library providing a binding to OpenCV-3.x.
+description: <>
+ .
+ This is a Haskell library providing a binding to OpenCV-3.x.
It binds directly with the C++ API using the @inline-c@ Haskell library.
.
The library is far from complete but the framework is there to easily
bind missing functionality.
+ .
+ Note that the OpenCV contrib modules are provided by
+ .
+ .
+ Make sure to checkout the
+ .
extra-source-files:
+ CHANGELOG.md
data/*.png
data/*.jpg
@@ -26,6 +35,11 @@ extra-doc-files:
doc/generated/examples/*.gif
doc/color_conversions.png
+source-repository head
+ type: git
+ location: git://github.com/LumiGuide/haskell-opencv.git
+ subdir: opencv
+
flag internal-documentation
description: Enables documentation generation for internal modules.
default: False
diff --git a/opencv/opencv.nix b/opencv/opencv.nix
index a28674cc..80ed9954 100644
--- a/opencv/opencv.nix
+++ b/opencv/opencv.nix
@@ -103,8 +103,8 @@ mkDerivation ({
libraryPkgconfigDepends = [ opencv3 ];
configureFlags =
- [ "--with-gcc=g++"
- "--with-ld=g++"
+ [ "--with-gcc=${stdenv.cc}/bin/c++"
+ "--with-ld=${stdenv.cc}/bin/c++"
];
hardeningDisable = [ "bindnow" ];
diff --git a/opencv/src/OpenCV/Calib3d.hs b/opencv/src/OpenCV/Calib3d.hs
index bd62c493..d4619429 100644
--- a/opencv/src/OpenCV/Calib3d.hs
+++ b/opencv/src/OpenCV/Calib3d.hs
@@ -3,9 +3,12 @@
module OpenCV.Calib3d
( FundamentalMatMethod(..)
+ , FindHomographyMethod(..)
+ , FindHomographyParams(..)
, WhichImage(..)
-- , calibrateCamera
, findFundamentalMat
+ , findHomography
, computeCorrespondEpilines
) where
@@ -14,6 +17,7 @@ import "base" Data.Word
import "base" Foreign.C.Types
import qualified "inline-c" Language.C.Inline as C
import qualified "inline-c-cpp" Language.C.Inline.Cpp as C
+import "data-default" Data.Default
import "this" OpenCV.Internal.C.Inline ( openCvCtx )
import "this" OpenCV.Internal.C.Types
import "this" OpenCV.Internal.Calib3d.Constants
@@ -57,6 +61,24 @@ marshalWhichImage = \case
Image1 -> 1
Image2 -> 2
+data FindHomographyMethod
+ = FindHomographyMethod_0
+ -- ^ A regular method using all the points.
+ | FindHomographyMethod_RANSAC
+ -- ^ RANSAC-based robust method.
+ | FindHomographyMethod_LMEDS
+ -- ^ Least-Median robust method.
+ | FindHomographyMethod_RHO
+ -- ^ PROSAC-based robust method.
+ deriving (Show)
+
+marshalFindHomographyMethod :: FindHomographyMethod -> Int32
+marshalFindHomographyMethod = \case
+ FindHomographyMethod_0 -> 0
+ FindHomographyMethod_RANSAC -> c'RANSAC
+ FindHomographyMethod_LMEDS -> c'LMEDS
+ FindHomographyMethod_RHO -> c'RHO
+
--------------------------------------------------------------------------------
-- {- |
@@ -110,7 +132,7 @@ findFundamentalMat
findFundamentalMat pts1 pts2 method = do
(fm, pointMask) <- c'findFundamentalMat
-- If the c++ function can't find a fundamental matrix it will
- -- retrun an empty matrix. We check for this case by trying to
+ -- return an empty matrix. We check for this case by trying to
-- coerce the result to the desired type.
catchE (Just . (, unsafeCoerceMat pointMask) <$> coerceMat fm)
(\case CoerceMatError _msgs -> pure Nothing
@@ -118,7 +140,7 @@ findFundamentalMat pts1 pts2 method = do
)
where
c'findFundamentalMat = unsafeWrapException $ do
- fm <- newEmptyMat
+ fm <- newEmptyMat
pointMask <- newEmptyMat
handleCvException (pure (fm, pointMask)) $
withPtr fm $ \fmPtr ->
@@ -143,6 +165,70 @@ findFundamentalMat pts1 pts2 method = do
c'numPts2 = fromIntegral $ V.length pts2
(c'method, c'p1, c'p2) = marshalFundamentalMatMethod method
+data FindHomographyParams
+ = FindHomographyParams
+ { fhpMethod :: !FindHomographyMethod
+ , fhpRansacReprojThreshold :: !Double
+ , fhpMaxIters :: !Int
+ , fhpConfidence :: !Double
+ } deriving (Show)
+
+instance Default FindHomographyParams where
+ def = FindHomographyParams
+ { fhpMethod = FindHomographyMethod_0
+ , fhpRansacReprojThreshold = 3
+ , fhpMaxIters = 2000
+ , fhpConfidence = 0.995
+ }
+
+findHomography
+ :: (IsPoint2 point2 CDouble)
+ => V.Vector (point2 CDouble) -- ^ Points from the first image.
+ -> V.Vector (point2 CDouble) -- ^ Points from the second image.
+ -> FindHomographyParams
+ -> CvExcept ( Maybe ( Mat ('S '[ 'S 3, 'S 3 ]) ('S 1) ('S Double)
+ , Mat ('S '[ 'D, 'D ]) ('S 1) ('S Word8 )
+ )
+ )
+findHomography srcPoints dstPoints fhp = do
+ (fm, pointMask) <- c'findHomography
+ -- If the c++ function can't find a fundamental matrix it will
+ -- return an empty matrix. We check for this case by trying to
+ -- coerce the result to the desired type.
+ catchE (Just . (, unsafeCoerceMat pointMask) <$> coerceMat fm)
+ (\case CoerceMatError _msgs -> pure Nothing
+ otherError -> throwE otherError
+ )
+ where
+ c'findHomography = unsafeWrapException $ do
+ fm <- newEmptyMat
+ pointMask <- newEmptyMat
+ handleCvException (pure (fm, pointMask)) $
+ withPtr fm $ \fmPtr ->
+ withPtr pointMask $ \pointMaskPtr ->
+ withArrayPtr (V.map toPoint srcPoints) $ \srcPtr ->
+ withArrayPtr (V.map toPoint dstPoints) $ \dstPtr ->
+ [cvExcept|
+ cv::_InputArray srcPts = cv::_InputArray($(Point2d * srcPtr), $(int32_t c'numSrcPts));
+ cv::_InputArray dstPts = cv::_InputArray($(Point2d * dstPtr), $(int32_t c'numDstPts));
+ *$(Mat * fmPtr) =
+ cv::findHomography
+ ( srcPts
+ , dstPts
+ , $(int32_t c'method)
+ , $(double c'ransacReprojThreshold)
+ , *$(Mat * pointMaskPtr)
+ , $(int32_t c'maxIters)
+ , $(double c'confidence)
+ );
+ |]
+ c'numSrcPts = fromIntegral $ V.length srcPoints
+ c'numDstPts = fromIntegral $ V.length dstPoints
+ c'method = marshalFindHomographyMethod $ fhpMethod fhp
+ c'ransacReprojThreshold = realToFrac $ fhpRansacReprojThreshold fhp
+ c'maxIters = fromIntegral $ fhpMaxIters fhp
+ c'confidence = realToFrac $ fhpConfidence fhp
+
{- | For points in an image of a stereo pair, computes the corresponding epilines in the other image
diff --git a/opencv/src/OpenCV/Core/ArrayOps.hs b/opencv/src/OpenCV/Core/ArrayOps.hs
index 6a669df6..c528d281 100644
--- a/opencv/src/OpenCV/Core/ArrayOps.hs
+++ b/opencv/src/OpenCV/Core/ArrayOps.hs
@@ -44,6 +44,8 @@ module OpenCV.Core.ArrayOps
, meanStdDev
, matFlip, FlipDirection(..)
, matTranspose
+ , hconcat
+ , vconcat
) where
import "base" Data.Proxy ( Proxy(..) )
@@ -922,3 +924,77 @@ matTranspose src = unsafePerformIO $ do
cv::transpose(*$(Mat * srcPtr), *$(Mat * dstPtr));
}|]
pure $ unsafeCoerceMat dst
+
+{- | Applies horizontal concatenation to given matrices.
+
+Example:
+
+@
+hconcatImg :: Mat ('S '[ 'D, 'D ]) ('S 3) ('S Word8)
+hconcatImg = exceptError $
+ hconcat $ V.fromList
+ [ halfSize birds_768x512
+ , halfSize flower_768x512
+ , halfSize sailboat_768x512
+ ]
+ where
+ halfSize = exceptError . resize (ResizeRel 0.5) InterArea
+@
+
+<>
+-}
+hconcat
+ :: V.Vector (Mat ('S '[rows, 'D]) channels depth)
+ -> CvExcept (Mat ('S '[rows, 'D]) channels depth)
+hconcat mats = unsafeWrapException $ do
+ dst <- unsafeCoerceMat <$> newEmptyMat
+ handleCvException (pure dst) $
+ withArrayPtr mats $ \matsPtr ->
+ withPtr dst $ \dstPtr ->
+ [cvExcept|
+ cv::hconcat
+ ( $(Mat * matsPtr)
+ , $(size_t c'numMats)
+ , *$(Mat * dstPtr)
+ );
+ |]
+ where
+ c'numMats :: C.CSize
+ c'numMats = fromIntegral $ V.length mats
+
+{- | Applies vertical concatenation to given matrices.
+
+Example:
+
+@
+vconcatImg :: Mat ('S '[ 'D, 'D ]) ('S 3) ('S Word8)
+vconcatImg = exceptError $
+ vconcat $ V.fromList
+ [ halfSize birds_768x512
+ , halfSize flower_768x512
+ , halfSize sailboat_768x512
+ ]
+ where
+ halfSize = exceptError . resize (ResizeRel 0.5) InterArea
+@
+
+<>
+-}
+vconcat
+ :: V.Vector (Mat ('S '[ 'D, cols ]) channels depth)
+ -> CvExcept (Mat ('S '[ 'D, cols ]) channels depth)
+vconcat mats = unsafeWrapException $ do
+ dst <- unsafeCoerceMat <$> newEmptyMat
+ handleCvException (pure dst) $
+ withArrayPtr mats $ \matsPtr ->
+ withPtr dst $ \dstPtr ->
+ [cvExcept|
+ cv::vconcat
+ ( $(Mat * matsPtr)
+ , $(size_t c'numMats)
+ , *$(Mat * dstPtr)
+ );
+ |]
+ where
+ c'numMats :: C.CSize
+ c'numMats = fromIntegral $ V.length mats
diff --git a/opencv/src/OpenCV/Internal/Calib3d/Constants.hsc b/opencv/src/OpenCV/Internal/Calib3d/Constants.hsc
index 2da3dc39..e9756106 100644
--- a/opencv/src/OpenCV/Internal/Calib3d/Constants.hsc
+++ b/opencv/src/OpenCV/Internal/Calib3d/Constants.hsc
@@ -16,3 +16,8 @@ module OpenCV.Internal.Calib3d.Constants where
#num CV_FM_8POINT
#num CV_FM_RANSAC
#num CV_FM_LMEDS
+
+#num LMEDS
+#num RANSAC
+#num RHO
+