Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
pano_unwrap.c
Go to the documentation of this file.
1/*
2 * Copyright (C) Tom van Dijk
3 *
4 * This file is part of paparazzi
5 *
6 * paparazzi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * paparazzi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with paparazzi; see the file COPYING. If not, see
18 * <http://www.gnu.org/licenses/>.
19 */
27
28#include "state.h"
30
31#include <stdio.h>
32
33#ifndef PANO_UNWRAP_CAMERA
34#define PANO_UNWRAP_CAMERA bottom_camera
35#endif
36
37#ifndef PANO_UNWRAP_CENTER_X
38#define PANO_UNWRAP_CENTER_X 0.50
39#endif
40#ifndef PANO_UNWRAP_CENTER_Y
41#define PANO_UNWRAP_CENTER_Y 0.50
42#endif
43#ifndef PANO_UNWRAP_RADIUS_BOTTOM
44#define PANO_UNWRAP_RADIUS_BOTTOM 0.20
45#endif
46#ifndef PANO_UNWRAP_RADIUS_TOP
47#define PANO_UNWRAP_RADIUS_TOP 0.30
48#endif
49#ifndef PANO_UNWRAP_FORWARD_DIRECTION
50#define PANO_UNWRAP_FORWARD_DIRECTION 270.0
51#endif
52#ifndef PANO_UNWRAP_FLIP_HORIZONTAL
53#define PANO_UNWRAP_FLIP_HORIZONTAL FALSE
54#endif
55
56#ifndef PANO_UNWRAP_VERTICAL_RESOLUTION
57#define PANO_UNWRAP_VERTICAL_RESOLUTION 0.18
58#endif
59#ifndef PANO_UNWRAP_DEROTATE_ATTITUDE
60#define PANO_UNWRAP_DEROTATE_ATTITUDE FALSE
61#endif
62
63#ifndef PANO_UNWRAP_WIDTH
64#define PANO_UNWRAP_WIDTH 640
65#endif
66#ifndef PANO_UNWRAP_HEIGHT
67#define PANO_UNWRAP_HEIGHT 0
68#endif
69
70#ifndef PANO_UNWRAP_OVERWRITE_VIDEO_THREAD
71#define PANO_UNWRAP_OVERWRITE_VIDEO_THREAD TRUE
72#endif
73
74#ifndef PANO_UNWRAP_FPS
75#define PANO_UNWRAP_FPS 0
76#endif
77
79 .center = {
82 },
83 .radius_bottom = PANO_UNWRAP_RADIUS_BOTTOM,
84 .radius_top = PANO_UNWRAP_RADIUS_TOP,
85 .forward_direction = PANO_UNWRAP_FORWARD_DIRECTION,
86 .flip_horizontal = PANO_UNWRAP_FLIP_HORIZONTAL,
87
88 .vertical_resolution = PANO_UNWRAP_VERTICAL_RESOLUTION,
89 .derotate_attitude = PANO_UNWRAP_DEROTATE_ATTITUDE,
90
91 .width = PANO_UNWRAP_WIDTH,
92 .height = PANO_UNWRAP_HEIGHT,
93
94 .overwrite_video_thread = PANO_UNWRAP_OVERWRITE_VIDEO_THREAD,
95
96 .show_calibration = FALSE,
97};
98
100
101#define PIXEL_U(img,x,y) ( ((uint8_t*)((img)->buf))[4*(int)((x)/2) + 2*(y)*(img)->w] )
102#define PIXEL_V(img,x,y) ( ((uint8_t*)((img)->buf))[4*(int)((x)/2) + 2*(y)*(img)->w + 2] )
103#define PIXEL_Y(img,x,y) ( ((uint8_t*)((img)->buf))[2*(x) + 1 + 2*(y)*(img)->w] )
104
105#define RED_Y 76
106#define RED_U 84
107#define RED_V 255
108#define GREEN_Y 149
109#define GREEN_U 43
110#define GREEN_V 21
111#define BLUE_Y 29
112#define BLUE_U 255
113#define BLUE_V 107
114
115struct LUT_t
116{
117 // Unwarping LUT
118 // For each pixel (u,v) in the unwrapped image, contains pixel coordinates of
119 // the same pixel in the raw image (x(u,v), y(u,v)).
122 // Derotate LUT
123 // For each bearing/column (u), contains the direction in which sampling should be
124 // shifted based on euler angles phi and theta dxy(phi|u) dxy(theta|u).
127 // Settings for which the LUT was generated
129};
130static struct LUT_t LUT; // Note: initialized NULL
131
132static void set_output_image_size(void)
133{
134 // Find vertical size of output image
135 if (pano_unwrap.height == 0) {
139 printf("[pano_unwrap] Automatic output image height: %d\n",
141 }
142 // Replace output image if required
145 printf("[pano_unwrap] Creating output image with size %d x %d\n",
150 }
151}
152
153static void update_LUT(const struct image_t *img)
154{
163 // LUT is still valid, do nothing
164 return;
165 }
166
167 printf("[pano_unwrap] Regenerating LUT... ");
168 // Remove old data
169 if (LUT.x) {
170 free(LUT.x);
171 LUT.x = NULL;
172 }
173 if (LUT.y) {
174 free(LUT.y);
175 LUT.y = NULL;
176 }
177 if (LUT.dphi) {
178 free(LUT.dphi);
179 LUT.dphi = NULL;
180 }
181 if (LUT.dtheta) {
182 free(LUT.dtheta);
183 LUT.dtheta = NULL;
184 }
185 // Generate unwarping LUT
188 if (!LUT.x || !LUT.y) {
189 printf("[pano_unwrap] ERROR could not allocate x or y lookup table!\n");
190 } else {
191 for (uint16_t u = 0; u < pano_unwrap.width; u++) {
192 float bearing = -M_PI + (float) u / pano_unwrapped_image.w * 2 * M_PI;
193 float angle = (pano_unwrap.forward_direction / 180.0 * M_PI)
194 + bearing * (pano_unwrap.flip_horizontal ? 1.f : -1.f);
195 float c = cosf(angle);
196 float s = sinf(angle);
197 for (uint16_t v = 0; v < pano_unwrap.height; v++) {
198 float radius = pano_unwrap.radius_top
200 * ((float) v / (pano_unwrap.height - 1));
201 LUT.x[v + u * pano_unwrap.height] = (uint16_t) (img->w
202 * pano_unwrap.center.x + c * radius * img->h + 0.5);
203 LUT.y[v + u * pano_unwrap.height] = (uint16_t) (img->h
204 * pano_unwrap.center.y - s * radius * img->h + 0.5);
205 }
206 }
207 }
208 // Generate derotation LUT
209 LUT.dphi = malloc(sizeof(*LUT.dphi) * pano_unwrap.width);
211 if (!LUT.dphi || !LUT.dtheta) {
212 printf(
213 "[pano_unwrap] ERROR could not allocate dphi or dtheta lookup table!\n");
214 } else {
215 for (uint16_t u = 0; u < pano_unwrap.width; u++) {
216 float bearing = -M_PI + (float) u / pano_unwrapped_image.w * 2 * M_PI;
217 float angle = (pano_unwrap.forward_direction / 180.0 * M_PI)
218 + bearing * (pano_unwrap.flip_horizontal ? 1.f : -1.f);
219 LUT.dphi[u].x = sinf(bearing) * cosf(angle);
220 LUT.dphi[u].y = sinf(bearing) * -sinf(angle);
221 LUT.dtheta[u].x = cosf(bearing) * cosf(angle);
222 LUT.dtheta[u].y = cosf(bearing) * -sinf(angle);
223 }
224 }
225 // Keep track of settings for which this LUT was generated
227 printf("ok\n");
228}
229
230static void unwrap_LUT(struct image_t *img_raw, struct image_t *img)
231{
232 for (uint16_t u = 0; u < pano_unwrap.width; u++) {
233 // Derotation offset for this bearing
234 int16_t dx = 0;
235 int16_t dy = 0;
237 // Look up correction
238 const struct FloatRMat *R = stateGetNedToBodyRMat_f();
240 * (LUT.dphi[u].x * MAT33_ELMT(*R, 1, 2)
241 + LUT.dtheta[u].x * MAT33_ELMT(*R, 0, 2)));
243 * (LUT.dphi[u].y * MAT33_ELMT(*R, 1, 2)
244 + LUT.dtheta[u].y * MAT33_ELMT(*R, 0, 2)));
245 }
246 // Fill this column of unwrapped image
247 for (uint16_t v = 0; v < pano_unwrap.height; v++) {
248 // Look up sampling point
249 int16_t x = (int16_t) LUT.x[v + u * pano_unwrap.height] + dx;
250 int16_t y = (int16_t) LUT.y[v + u * pano_unwrap.height] + dy;
251 // Check bounds
252 if (x < 0) {
253 x = 0;
254 } else if (x > img_raw->w - 1) {
255 x = img_raw->w - 1;
256 }
257 if (y < 0) {
258 y = 0;
259 } else if (y > img_raw->h - 1) {
260 y = img_raw->h - 1;
261 }
262 // Draw calibration pattern
264 if (v == 0 || v == pano_unwrap.height - 1) {
265 PIXEL_U(img_raw,x,y) = BLUE_U;
266 PIXEL_V(img_raw,x,y) = BLUE_V;
267 }
268 if ((u == pano_unwrap.width / 2)
269 || (u == pano_unwrap.width / 2 + 1)) {
270 PIXEL_Y(img_raw,x,y) = RED_Y;
271 PIXEL_U(img_raw,x,y) = RED_U;
272 PIXEL_V(img_raw,x,y) = RED_V;
273 }
274 if ((u == 3 * pano_unwrap.width / 4)
275 || (u == 3 * pano_unwrap.width / 4 + 1)) {
276 PIXEL_Y(img_raw,x,y) = GREEN_Y;
277 PIXEL_U(img_raw,x,y) = GREEN_U;
278 PIXEL_V(img_raw,x,y) = GREEN_V;
279 }
280 }
281 // Copy pixel values
282 PIXEL_Y(img,u,v) = PIXEL_Y(img_raw, x, y);
283 PIXEL_U(img,u,v) = PIXEL_U(img_raw, x, y);
284 PIXEL_V(img,u,v) = PIXEL_V(img_raw, x, y);
285 }
286 }
287 // Draw lens center
291 for (int i = -5; i <= 5; i++) {
292 for (int j = -5; j <= 5; j++) {
293 if (i == 0 || j == 0) {
294 PIXEL_Y(img_raw, x+i, y+j) = BLUE_Y;
295 PIXEL_U(img_raw, x+i, y+j) = BLUE_U;
296 PIXEL_V(img_raw, x+i, y+j) = BLUE_V;
297 }
298 }
299 }
300 }
301}
302
312
319
struct video_listener * cv_add_to_device(struct video_config_t *device, cv_function func, uint16_t fps, uint8_t id)
Definition cv.c:46
Computer vision framework for onboard processing.
rotation matrix
#define MAT33_ELMT(_m, _row, _col)
static struct FloatRMat * stateGetNedToBodyRMat_f(void)
Get vehicle body attitude rotation matrix (float).
Definition state.h:1300
void image_free(struct image_t *img)
Free the image.
Definition image.c:75
void image_create(struct image_t *img, uint16_t width, uint16_t height, enum image_type type)
Create a new image.
Definition image.c:43
struct timeval ts
The timestamp of creation.
Definition image.h:48
uint32_t pprz_ts
The timestamp in us since system startup.
Definition image.h:50
uint16_t h
Image height.
Definition image.h:47
uint16_t w
Image width.
Definition image.h:46
@ IMAGE_YUV422
UYVY format (uint16 per pixel)
Definition image.h:36
static uint32_t s
uint16_t foo
Definition main_demo5.c:58
#define PANO_UNWRAP_RADIUS_TOP
Definition pano_unwrap.c:47
#define RED_V
uint16_t * x
void pano_unwrap_init()
#define BLUE_Y
#define PANO_UNWRAP_DEROTATE_ATTITUDE
Definition pano_unwrap.c:60
static void set_output_image_size(void)
#define PANO_UNWRAP_FORWARD_DIRECTION
Definition pano_unwrap.c:50
#define PIXEL_U(img, x, y)
static struct LUT_t LUT
#define PANO_UNWRAP_HEIGHT
Definition pano_unwrap.c:67
#define PANO_UNWRAP_CENTER_X
Definition pano_unwrap.c:38
static void unwrap_LUT(struct image_t *img_raw, struct image_t *img)
#define RED_Y
#define GREEN_U
#define PANO_UNWRAP_WIDTH
Definition pano_unwrap.c:64
#define BLUE_U
struct image_t pano_unwrapped_image
Unwrapped panoramic image.
Definition pano_unwrap.c:99
#define PANO_UNWRAP_CAMERA
Definition pano_unwrap.c:34
#define PIXEL_Y(img, x, y)
#define PANO_UNWRAP_OVERWRITE_VIDEO_THREAD
Definition pano_unwrap.c:71
struct pano_unwrap_t pano_unwrap
Definition pano_unwrap.c:78
#define PANO_UNWRAP_CENTER_Y
Definition pano_unwrap.c:41
#define PANO_UNWRAP_FLIP_HORIZONTAL
Definition pano_unwrap.c:53
#define GREEN_V
static void update_LUT(const struct image_t *img)
#define PIXEL_V(img, x, y)
uint16_t * y
#define PANO_UNWRAP_FPS
Definition pano_unwrap.c:75
static struct image_t * camera_cb(struct image_t *img, uint8_t camera_id)
#define PANO_UNWRAP_VERTICAL_RESOLUTION
Definition pano_unwrap.c:57
#define RED_U
#define BLUE_V
#define GREEN_Y
struct FloatVect2 * dtheta
struct pano_unwrap_t settings
struct FloatVect2 * dphi
#define PANO_UNWRAP_RADIUS_BOTTOM
Definition pano_unwrap.c:44
float radius_top
Distance from center point to top of region of interest [fraction of image height].
Definition pano_unwrap.h:35
float forward_direction
Angle [deg] in raw image that corresponds to the forward direction, where 0 points right and the valu...
Definition pano_unwrap.h:36
bool overwrite_video_thread
Set to true if the unwrapped image should be returned to the video thread.
Definition pano_unwrap.h:45
uint16_t width
Width of unwrapped image.
Definition pano_unwrap.h:42
uint16_t height
Height of unwrapped image. Set to 0 (default) to determine automatically from unwrapped_width,...
Definition pano_unwrap.h:43
bool derotate_attitude
Set to true if roll/pitch movement should be corrected.
Definition pano_unwrap.h:40
bool show_calibration
Draw calibration pattern on raw image.
Definition pano_unwrap.h:47
bool flip_horizontal
Set to true to horizontally flip the unwrapped image.
Definition pano_unwrap.h:37
float vertical_resolution
Vertical resolution of raw image in the region of interest, used for attitude derotation [fraction of...
Definition pano_unwrap.h:39
struct FloatVect2 center
Center point of panoramic lens [fraction of image width, height].
Definition pano_unwrap.h:33
float radius_bottom
Distance from center point to bottom of region of interest [fraction of image height].
Definition pano_unwrap.h:34
API to get/set the generic vehicle states.
#define FALSE
Definition std.h:5
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
short int16_t
Typedef defining 16 bit short type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.