module #include "dip_opencv_interface.h"
DIPlib-OpenCV interface Functions to convert images to and from OpenCV.
Contents
- Limitations
- Reference
The dip_opencv
namespace defines the functions needed to convert between OpenCV cv::Mat
objects and DIPlib
dip::Image
objects.
We define a class dip_opencv::ExternalInterface
so that output images from DIPlib can yield an OpenCV image.
The function dip_opencv::MatToDip
encapsulates (maps) an OpenCV image in a DIPlib image;
dip_opencv::DipToMat
does the opposite, mapping a DIPlib image as an OpenCV image.
Limitations
OpenCV is more limited in how the pixel data is stored, and consequently not all DIPlib images can be mapped as an OpenCV image. These are the limitations:
-
The maximum number of channels in OpenCV is
CV_CN_MAX
(equal to 512 in my copy). DIPlib tensor elements are mapped to channels, but the tensor shape is lost. The tensor stride must be 1. -
OpenCV recognizes the following types (depths): 8-bit and 16-bit signed and unsigned ints, 32-bit signed ints, and 32-bit and 64-bit floats. Thus,
dip::DT_UINT32
cannot be mapped. We choose to map it to 32-bit signed ints, with the potential problem that the upper half of the unsigned range is mapped to negative values (all modern systems use two’s complement).dip::DT_BIN
is mapped to an 8-bit unsigned integer, see the note below. 64-bit integer images cannot be mapped and throw an exception. -
Complex pixel values are mapped to
CV_32FC2
orCV_64FC2
– a 2-channel floatcv::Mat
array. Consequently, complex-valued tensor images cannot be mapped. -
cv::Mat
objects can store arrays of any dimensionality larger than 2, but OpenCV functionality is mostly limited to 2D images. Therefore, we only map 2Ddip::Image
objects in acv::Mat
array. 0D or 1D images will have singleton dimensions appended to force them to be 2D. -
In OpenCV, the image rows must be contiguous (i.e. the x-stride must be equal to the number of tensor elements), and the y-stride must be positive. This matches DIPlib’s default, but if the
dip::Image
object has strides that don’t match OpenCV’s requirement (e.g. after extracting a non-contiguous subset of pixels, or callingdip::Image::Mirror
ordip::Image::Rotation90
), an exception will be thrown. Usedip::Image::ForceNormalStrides
to copy the image into a suitable order for mapping. Alternatively, usedip_opencv::CopyDipToMat
.
Namespaces
- namespace dip_opencv
- The
dip_opencv
namespace contains the interface between OpenCV 2 (or later) and DIPlib.
Classes
-
class dip_opencv::
ExternalInterface - This class is the
dip::ExternalInterface
for the OpenCV interface.
Functions
-
auto dip_opencv::
MatToDip(cv::Mat const& mat, bool forceUnsigned = false) -> dip::Image - Creates a DIPlib image around an OpenCV
cv::Mat
, without taking ownership of the data. -
auto dip_opencv::
DipToMat(dip::Image const& img) -> cv::Mat - Creates an OpenCV
cv::Mat
object around a DIPlib image, without taking ownership of the data. -
auto dip_opencv::
CopyDipToMat(dip::Image const& img) -> cv::Mat - Creates an OpenCV
cv::Mat
object from a DIPlib image by copy. -
void dip_opencv::
FixBinaryImageForDip(dip::Image& img) - Fixes the binary image
img
to match expectations of DIPlib (i.e. only the bottom bit is used). -
void dip_opencv::
FixBinaryImageForOpenCv(dip::Image& img) - Fixes the binary image
img
to match expectations of OpenCV (i.e. all bits have the same value).
Function documentation
dip::Image
dip_opencv:: MatToDip(cv::Mat const& mat,
bool forceUnsigned = false)
Creates a DIPlib image around an OpenCV cv::Mat
, without taking ownership of the data.
This function maps a cv::Mat
object to a dip::Image
object.
The dip::Image
object will point to the data in the cv::Mat
, which must continue existing until the
dip::Image
is deleted or stripped. The output dip::Image
is protected to prevent accidental reforging,
unprotect it using dip::Image::Protect
.
An empty cv::Mat
produces a non-forged dip::Image
.
If the OpenCV image mat
has depth CV_32S
(32-bit signed integer), and forceUnsigned
is true
, then
the output dip::Image
will be of type dip::DT_UINT32
, instead of dip::DT_SINT32
.
For a “binary” OpenCV image (these are images of type CV_8U
with pixel values of 0 and 255), the mapped
DIPlib image is of type dip::DT_UINT8
, because this function cannot know if the input mat
was used as
an 8-bit unsigned integer image or as a binary image. The simplest way to obtain a binary DIPlib image is
to threshold the output of MatToDip
. However, this leads to an image that doesn’t share the data segment
with the original mat
:
cv::Mat bin_mat = cv::threshold(...); // This is a "binary" OpenCV image dip::Image bin_dip = dip_opencv::MatToDip( bin_mat ); // This is a dip::DT_UINT8 DIPlib image, not dip::DT_BIN bin_dip = bin_dip > 0;
There currently is no simple solution to creating a dip::DT_BIN
image that encapsulates the data from a
cv::Mat
image. However, one can encapsulate the data of a binary dip::Image
in a cv::Mat
, see the example
in dip_opencv::FixBinaryImageForOpenCv
.
cv::Mat
dip_opencv:: DipToMat(dip::Image const& img)
Creates an OpenCV cv::Mat
object around a DIPlib image, without taking ownership of the data.
This function maps a dip::Image
object to a cv::Mat
object.
The cv::Mat
object will point to the data in the dip::Image
, which must continue existing until the
cv::Mat
is deleted.
A non-forged dip::Image
produces an empty cv::Mat
.
There are many limitations to the images that can be mapped by a cv::Mat
, see the description in the
documentation to the module: DIPlib-OpenCV interface. You can also use dip_opencv::CopyDipToMat
instead.
cv::Mat
dip_opencv:: CopyDipToMat(dip::Image const& img)
Creates an OpenCV cv::Mat
object from a DIPlib image by copy.
A non-forged dip::Image
produces an empty cv::Mat
.
If the image has more than two dimensions, or is a complex-valued tensor image, no copy can be made; an exception will be thrown.
void
dip_opencv:: FixBinaryImageForDip(dip::Image& img)
Fixes the binary image img
to match expectations of DIPlib (i.e. only the bottom bit is used).
The input image is expected to be binary. See dip_opencv::FixBinaryImageForOpenCv
for a use case.
void
dip_opencv:: FixBinaryImageForOpenCv(dip::Image& img)
Fixes the binary image img
to match expectations of OpenCV (i.e. all bits have the same value).
The input image is expected to be binary. The data segment for the image is modified such that it is no longer useful for use in DIPlib, but becomes useful for use in OpenCV.
dip::Image bin_dip = dip::Threshold(...); // This is a DIPlib binary image cv::Mat bin_mat = dip_opencv::DipToMat( bin_dip ); // This is an OpenCV CV_8U image with values 0 and 1 // use bin_dip with DIPlib functions here... dip_opencv::FixBinaryImageForOpenCv( bin_dip ); // Now both bin_dip and bin_mat have values 0 and 255 // use bin_mat with OpenCV functions here... dip_opencv::FixBinaryImageForDip( bin_dip ); // Now both bin_dip and bin_mat have values 0 and 1 // use bin_dip with DIPlib functions here...