1 /* GStreamer
2 * Copyright (C) <2010> Thiago Santos <thiago.sousa.santos@collabora.co.uk>
3 * Copyright (C) <2018> Nicola Murino <nicola.murino@gmail.com>
4 *
5 * gstopencvutils.c: miscellaneous utility functions
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "gstopencvutils.h"
28 #include <opencv2/core.hpp>
29
30 /*
31 The various opencv image containers or headers store the following information:
32 - number of channels (usually 1, 3 or 4)
33 - depth (8, 16, 32, 64...); all channels have the same depth.
34 The channel layout (BGR vs RGB) is not stored...
35
36 This gives us the following list of supported image formats:
37 CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4
38 CV_8SC1, CV_8SC2, CV_8SC3, CV_8SC4
39 CV_16UC1, CV_16UC2, CV_16UC3, CV_16UC4
40 CV_16SC1, CV_16SC2, CV_16SC3, CV_16SC4
41 CV_32SC1, CV_32SC2, CV_32SC3, CV_32SC4
42 CV_32FC1, CV_32FC2, CV_32FC3, CV_32FC4
43 CV_64FC1, CV_64FC2, CV_64FC3, CV_64FC4
44
45 Where the first part of the format name is the depth followed by a digit
46 representing the number of channels.
47 Note that opencv supports more that 4 channels.
48
49 The opencv algorithms don't all support all the image types.
50 For example findChessboardCorners() supports only 8 bits formats
51 (gray scale and color).
52
53 And, typically, this algorithm will convert the image to gray scale before
54 proceeding. It will do so with something like this:
55 cvtColor(srcImg, destImg, CV_BGR2GRAY);
56
57 The conversion will work on any BGR format (BGR, BGRA, BGRx).
58 The extra channel(s) will be ignored.
59 It will also produce a result for any RGB format.
60 The result will be "wrong" to the human eye and might affect some algorithms
61 (not findChessboardCorners() afaik...).
62 This is due to how RGB gets converted to gray where each color has a
63 different weight.
64
65 Another example is the 2D rendering API.
66 It work with RGB but the colors will be wrong.
67
68 Likewise other layouts like xBGR and ABGR formats will probably misbehave
69 with most algorithms.
70
71 The bad thing is that it is not possible to change the "default" BGR format.
72 Safest is to not assume that RGB will work and always convert to BGR.
73
74 That said, the current opencv gstreamer elements all accept BGR and RGB caps !
75 Some have restrictions but if a format is supported then both BGR and RGB
76 layouts will be supported.
77 */
78
gst_opencv_parse_cv_mat_params_from_caps(GstCaps * caps,gint * width,gint * height,int * cv_type,GError ** err)79 gboolean gst_opencv_parse_cv_mat_params_from_caps
80 (GstCaps * caps, gint * width, gint * height, int *cv_type, GError ** err)
81 {
82 GstVideoInfo info;
83 gchar *caps_str;
84
85 if (!gst_video_info_from_caps (&info, caps)) {
86 caps_str = gst_caps_to_string (caps);
87 GST_ERROR ("Failed to get video info from caps %s", caps_str);
88 g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_NEGOTIATION,
89 "Failed to get video info from caps %s", caps_str);
90 g_free (caps_str);
91 return FALSE;
92 }
93
94 return gst_opencv_cv_mat_params_from_video_info (&info, width, height,
95 cv_type, err);
96 }
97
gst_opencv_cv_mat_params_from_video_info(GstVideoInfo * info,gint * width,gint * height,int * cv_type,GError ** err)98 gboolean gst_opencv_cv_mat_params_from_video_info
99 (GstVideoInfo * info, gint * width, gint * height, int *cv_type,
100 GError ** err)
101 {
102 GstVideoFormat format;
103
104 format = GST_VIDEO_INFO_FORMAT (info);
105 if (!gst_opencv_cv_image_type_from_video_format (format, cv_type, err)) {
106 return FALSE;
107 }
108
109 *width = GST_VIDEO_INFO_WIDTH (info);
110 *height = GST_VIDEO_INFO_HEIGHT (info);
111
112 return TRUE;
113 }
114
115 gboolean
gst_opencv_cv_image_type_from_video_format(GstVideoFormat format,int * cv_type,GError ** err)116 gst_opencv_cv_image_type_from_video_format (GstVideoFormat format,
117 int *cv_type, GError ** err)
118 {
119 const gchar *format_str;
120
121 switch (format) {
122 case GST_VIDEO_FORMAT_GRAY8:
123 *cv_type = CV_8UC1;
124 break;
125 case GST_VIDEO_FORMAT_RGB:
126 case GST_VIDEO_FORMAT_BGR:
127 *cv_type = CV_8UC3;
128 break;
129 case GST_VIDEO_FORMAT_RGBx:
130 case GST_VIDEO_FORMAT_xRGB:
131 case GST_VIDEO_FORMAT_BGRx:
132 case GST_VIDEO_FORMAT_xBGR:
133 case GST_VIDEO_FORMAT_RGBA:
134 case GST_VIDEO_FORMAT_ARGB:
135 case GST_VIDEO_FORMAT_BGRA:
136 case GST_VIDEO_FORMAT_ABGR:
137 *cv_type = CV_8UC4;
138 break;
139 case GST_VIDEO_FORMAT_GRAY16_LE:
140 case GST_VIDEO_FORMAT_GRAY16_BE:
141 *cv_type = CV_16UC1;
142 break;
143 default:
144 format_str = gst_video_format_to_string (format);
145 g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_NEGOTIATION,
146 "Unsupported video format %s", format_str);
147 return FALSE;
148 }
149
150 return TRUE;
151 }
152
153 GstCaps *
gst_opencv_caps_from_cv_image_type(int cv_type)154 gst_opencv_caps_from_cv_image_type (int cv_type)
155 {
156 GstCaps *c = gst_caps_new_empty ();
157 switch (cv_type) {
158 case CV_8UC1:
159 gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("GRAY8")));
160 break;
161 case CV_8UC3:
162 gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("RGB")));
163 gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("BGR")));
164 break;
165 case CV_8UC4:
166 gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("RGBx")));
167 gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("xRGB")));
168 gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("BGRx")));
169 gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("xBGR")));
170 gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("RGBA")));
171 gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("ARGB")));
172 gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("BGRA")));
173 gst_caps_append (c, gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("ABGR")));
174 break;
175 case CV_16UC1:
176 gst_caps_append (c,
177 gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("GRAY16_LE")));
178 gst_caps_append (c,
179 gst_caps_from_string (GST_VIDEO_CAPS_MAKE ("GRAY16_BE")));
180 break;
181 }
182 return c;
183 }
184