| /* GStreamer |
| * Copyright (C) <2010> Thiago Santos <thiago.sousa.santos@collabora.co.uk> |
| * |
| * gstopencvutils.c: miscellaneous utility functions |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public |
| * License along with this library; if not, write to the |
| * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include "config.h" |
| #endif |
| |
| #include "gstopencvutils.h" |
| #include <opencv2/core/core_c.h> |
| |
| /* |
| The various opencv image containers or headers store the following information: |
| - number of channels (usually 1, 3 or 4) |
| - depth (8, 16, 32, 64...); all channels have the same depth. |
| The channel layout (BGR vs RGB) is not stored... |
| |
| This gives us the following list of supported image formats: |
| CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4 |
| CV_8SC1, CV_8SC2, CV_8SC3, CV_8SC4 |
| CV_16UC1, CV_16UC2, CV_16UC3, CV_16UC4 |
| CV_16SC1, CV_16SC2, CV_16SC3, CV_16SC4 |
| CV_32SC1, CV_32SC2, CV_32SC3, CV_32SC4 |
| CV_32FC1, CV_32FC2, CV_32FC3, CV_32FC4 |
| CV_64FC1, CV_64FC2, CV_64FC3, CV_64FC4 |
| |
| Where the first part of the format name is the depth followed by a digit |
| representing the number of channels. |
| Note that opencv supports more that 4 channels. |
| |
| The opencv algorithms don't all support all the image types. |
| For example findChessboardCorners() supports only 8 bits formats |
| (gray scale and color). |
| |
| And, typically, this algorithm will convert the image to gray scale before |
| proceeding. It will do so with something like this: |
| cvtColor(srcImg, destImg, CV_BGR2GRAY); |
| |
| The conversion will work on any BGR format (BGR, BGRA, BGRx). |
| The extra channel(s) will be ignored. |
| It will also produce a result for any RGB format. |
| The result will be "wrong" to the human eye and might affect some algorithms |
| (not findChessboardCorners() afaik...). |
| This is due to how RGB gets converted to gray where each color has a |
| different weight. |
| |
| Another example is the 2D rendering API. |
| It work with RGB but the colors will be wrong. |
| |
| Likewise other layouts like xBGR and ABGR formats will probably misbehave |
| with most algorithms. |
| |
| The bad thing is that it is not possible to change the "default" BGR format. |
| Safest is to not assume that RGB will work and always convert to BGR. |
| |
| That said, the current opencv gstreamer elements all accept BGR and RGB caps ! |
| Some have restrictions but if a format is supported then both BGR and RGB |
| layouts will be supported. |
| */ |
| |
| gboolean |
| gst_opencv_parse_iplimage_params_from_caps (GstCaps * caps, gint * width, |
| gint * height, gint * ipldepth, gint * channels, GError ** err) |
| { |
| GstVideoInfo info; |
| gchar *caps_str; |
| |
| if (!gst_video_info_from_caps (&info, caps)) { |
| caps_str = gst_caps_to_string (caps); |
| GST_ERROR ("Failed to get video info from caps %s", caps_str); |
| g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_NEGOTIATION, |
| "Failed to get video info from caps %s", caps_str); |
| g_free (caps_str); |
| return FALSE; |
| } |
| |
| return gst_opencv_iplimage_params_from_video_info (&info, width, height, |
| ipldepth, channels, err); |
| } |
| |
| gboolean |
| gst_opencv_iplimage_params_from_video_info (GstVideoInfo * info, gint * width, |
| gint * height, gint * ipldepth, gint * channels, GError ** err) |
| { |
| GstVideoFormat format; |
| int cv_type; |
| |
| format = GST_VIDEO_INFO_FORMAT (info); |
| if (!gst_opencv_cv_image_type_from_video_format (format, &cv_type, err)) { |
| return FALSE; |
| } |
| |
| *width = GST_VIDEO_INFO_WIDTH (info); |
| *height = GST_VIDEO_INFO_HEIGHT (info); |
| |
| *ipldepth = cvIplDepth (cv_type); |
| *channels = CV_MAT_CN (cv_type); |
| |
| return TRUE; |
| } |
| |
| gboolean |
| gst_opencv_cv_image_type_from_video_format (GstVideoFormat format, |
| int * cv_type, GError ** err) |
| { |
| const gchar *format_str; |
| |
| switch (format) { |
| case GST_VIDEO_FORMAT_GRAY8: |
| *cv_type = CV_8UC1; |
| break; |
| case GST_VIDEO_FORMAT_RGB: |
| case GST_VIDEO_FORMAT_BGR: |
| *cv_type = CV_8UC3; |
| break; |
| case GST_VIDEO_FORMAT_RGBx: |
| case GST_VIDEO_FORMAT_xRGB: |
| case GST_VIDEO_FORMAT_BGRx: |
| case GST_VIDEO_FORMAT_xBGR: |
| case GST_VIDEO_FORMAT_RGBA: |
| case GST_VIDEO_FORMAT_ARGB: |
| case GST_VIDEO_FORMAT_BGRA: |
| case GST_VIDEO_FORMAT_ABGR: |
| *cv_type = CV_8UC4; |
| break; |
| case GST_VIDEO_FORMAT_GRAY16_LE: |
| case GST_VIDEO_FORMAT_GRAY16_BE: |
| *cv_type = CV_16UC1; |
| break; |
| default: |
| format_str = gst_video_format_to_string (format); |
| g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_NEGOTIATION, |
| "Unsupported video format %s", format_str); |
| return FALSE; |
| } |
| |
| return TRUE; |
| } |
| |
| GstCaps * |
| gst_opencv_caps_from_cv_image_type (int cv_type) |
| { |
| GstCaps *c = gst_caps_new_empty (); |
| switch (cv_type) { |
| case CV_8UC1: |
| gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("GRAY8"))); |
| break; |
| case CV_8UC3: |
| gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("RGB"))); |
| gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("BGR"))); |
| break; |
| case CV_8UC4: |
| gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("RGBx"))); |
| gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("xRGB"))); |
| gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("BGRx"))); |
| gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("xBGR"))); |
| gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("RGBA"))); |
| gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("ARGB"))); |
| gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("BGRA"))); |
| gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("ABGR"))); |
| break; |
| case CV_16UC1: |
| gst_caps_append (c, |
| gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("GRAY16_LE"))); |
| gst_caps_append (c, |
| gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("GRAY16_BE"))); |
| break; |
| } |
| return c; |
| } |