Commit 0cdcf4baf3e1465a707bee67c5e63a8ec47e5758

Authored by Charles Otto
1 parent 47078a75

Somewhat more robust AdjacentOverlay

Fix some issues with bounding boxes not being clipped correctly.
If the overlay would go past the image boundary, expand the image instead
of clipping.
Showing 1 changed file with 120 additions and 8 deletions
openbr/plugins/draw.cpp
@@ -271,14 +271,27 @@ class AdjacentOverlayTransform : public Transform @@ -271,14 +271,27 @@ class AdjacentOverlayTransform : public Transform
271 void project(const Template &src, Template &dst) const 271 void project(const Template &src, Template &dst) const
272 { 272 {
273 dst = src; 273 dst = src;
  274 +
274 if (imgName.isEmpty() || targetName.isEmpty() || !dst.file.contains(imgName) || !dst.file.contains(targetName)) 275 if (imgName.isEmpty() || targetName.isEmpty() || !dst.file.contains(imgName) || !dst.file.contains(targetName))
275 return; 276 return;
276 277
277 - QString im_name = src.file.get<QString>(imgName); 278 + QVariant temp = src.file.value(imgName);
  279 + cv::Mat im;
  280 + // is this a filename?
  281 + if (temp.canConvert<QString>()) {
  282 + QString im_name = temp.toString();
  283 + Template temp_im;
  284 + opener->project(File(im_name), temp_im);
  285 + im = temp_im.m();
  286 + }
  287 + // a cv::Mat ?
  288 + else if (temp.canConvert<cv::Mat>())
  289 + im = src.file.get<cv::Mat>(imgName);
  290 + else
  291 + qDebug() << "Unrecognized property type " << imgName << "for" << src.file.name;
  292 +
  293 + // Location of detected face in source image
278 QRectF target_location = src.file.get<QRectF>(targetName); 294 QRectF target_location = src.file.get<QRectF>(targetName);
279 - Template temp_im;  
280 - opener->project(File(im_name), temp_im);  
281 - cv::Mat im = temp_im.m();  
282 295
283 // match width with target region 296 // match width with target region
284 qreal target_width = target_location.width(); 297 qreal target_width = target_location.width();
@@ -290,39 +303,137 @@ class AdjacentOverlayTransform : public Transform @@ -290,39 +303,137 @@ class AdjacentOverlayTransform : public Transform
290 303
291 cv::resize(im, im, cv::Size(target_width, target_height)); 304 cv::resize(im, im, cv::Size(target_width, target_height));
292 305
  306 + // ROI used to maybe crop the matched image
293 cv::Rect clip_roi; 307 cv::Rect clip_roi;
294 clip_roi.x = 0; 308 clip_roi.x = 0;
295 clip_roi.y = 0; 309 clip_roi.y = 0;
296 clip_roi.width = im.cols; 310 clip_roi.width = im.cols;
297 - clip_roi.height= im.rows; 311 + clip_roi.height= im.rows <= dst.m().rows ? im.rows : dst.m().rows;
298 312
299 int half_width = src.m().cols / 2; 313 int half_width = src.m().cols / 2;
300 int out_x = 0; 314 int out_x = 0;
  315 +
  316 + // place in the source image we will copy the matched image to.
301 cv::Rect target_roi; 317 cv::Rect target_roi;
  318 + bool left_side = false;
  319 + int width_adjust = 0;
302 // Place left 320 // Place left
303 if (target_location.center().rx() > half_width) { 321 if (target_location.center().rx() > half_width) {
304 out_x = target_location.left() - im.cols; 322 out_x = target_location.left() - im.cols;
305 if (out_x < 0) { 323 if (out_x < 0) {
306 - clip_roi.width += out_x; 324 + width_adjust = abs(out_x);
307 out_x = 0; 325 out_x = 0;
308 } 326 }
  327 + left_side = true;
309 } 328 }
310 // place right 329 // place right
311 else { 330 else {
312 out_x = target_location.right(); 331 out_x = target_location.right();
313 int high = out_x + im.cols; 332 int high = out_x + im.cols;
314 if (high >= src.m().cols) { 333 if (high >= src.m().cols) {
315 - clip_roi.width -= high - src.m().cols + 1; 334 + width_adjust = abs(high - src.m().cols + 1);
316 } 335 }
317 } 336 }
  337 +
  338 + cv::Mat outIm;
  339 + if (width_adjust)
  340 + {
  341 + outIm.create(dst.m().rows, dst.m().cols + width_adjust, CV_8UC3);
  342 + memset(outIm.data, 127, outIm.rows * outIm.cols * outIm.channels());
  343 +
  344 + Rect temp;
  345 +
  346 + if (left_side)
  347 + temp = Rect(abs(width_adjust), 0, dst.m().cols, dst.m().rows);
  348 +
  349 + else
  350 + temp = Rect(0, 0, dst.m().cols, dst.m().rows);
  351 +
  352 + dst.m().copyTo(outIm(temp));
  353 +
  354 + }
  355 + else
  356 + outIm = dst.m();
  357 +
  358 + if (clip_roi.height + target_location.top() >= outIm.rows)
  359 + {
  360 + clip_roi.height -= abs(outIm.rows - (clip_roi.height + target_location.top() ));
  361 + }
  362 + if (clip_roi.x + clip_roi.width >= im.cols) {
  363 + clip_roi.width -= abs(im.cols - (clip_roi.x + clip_roi.width + 1));
  364 + if (clip_roi.width < 0)
  365 + clip_roi.width = 1;
  366 + }
  367 +
  368 + if (clip_roi.y + clip_roi.height >= im.rows) {
  369 + clip_roi.height -= abs(im.rows - (clip_roi.y + clip_roi.height + 1));
  370 + }
  371 + if (clip_roi.x < 0)
  372 + clip_roi.x = 0;
  373 + if (clip_roi.y < 0)
  374 + clip_roi.y = 0;
  375 +
  376 + if (clip_roi.height < 0)
  377 + clip_roi.height = 0;
  378 +
  379 + if (clip_roi.width < 0)
  380 + clip_roi.width = 0;
  381 +
  382 +
  383 + if (clip_roi.y + clip_roi.height >= im.rows)
  384 + {
  385 + qDebug() << "Bad clip y" << clip_roi.y + clip_roi.height << im.rows;
  386 + }
  387 + if (clip_roi.x + clip_roi.width >= im.cols)
  388 + {
  389 + qDebug() << "Bad clip x" << clip_roi.x + clip_roi.width << im.cols;
  390 + }
  391 +
  392 + if (clip_roi.y < 0 || clip_roi.height < 0)
  393 + {
  394 + qDebug() << "bad clip y, low" << clip_roi.y << clip_roi.height;
  395 + qFatal("die");
  396 + }
  397 + if (clip_roi.x < 0 || clip_roi.width < 0)
  398 + {
  399 + qDebug() << "bad clip x, low" << clip_roi.x << clip_roi.width;
  400 + qFatal("die");
  401 + }
  402 +
318 target_roi.x = out_x; 403 target_roi.x = out_x;
319 target_roi.width = clip_roi.width; 404 target_roi.width = clip_roi.width;
320 target_roi.y = target_location.top(); 405 target_roi.y = target_location.top();
321 target_roi.height = clip_roi.height; 406 target_roi.height = clip_roi.height;
322 407
  408 +
323 im = im(clip_roi); 409 im = im(clip_roi);
324 410
325 - cv::Mat outIm = dst.m(); 411 + if (target_roi.x < 0 || target_roi.x >= outIm.cols)
  412 + {
  413 + qDebug() << "Bad xdim in targetROI!" << target_roi.x << " out im x: " << outIm.cols;
  414 + qFatal("die");
  415 + }
  416 +
  417 + if (target_roi.x + target_roi.width < 0 || (target_roi.x + target_roi.width) >= outIm.cols)
  418 + {
  419 + qDebug() << "Bad xdim in targetROI!" << target_roi.x + target_roi.width;
  420 + qFatal("die");
  421 + }
  422 +
  423 + if (target_roi.y < 0 || target_roi.y >= outIm.rows)
  424 + {
  425 + qDebug() << "Bad ydim in targetROI!" << target_roi.y;
  426 + qFatal("die");
  427 + }
  428 +
  429 + if ((target_roi.y + target_roi.height) < 0 || (target_roi.y + target_roi.height) > outIm.rows)
  430 + {
  431 + qDebug() << "Bad ydim in targetROI!" << target_roi.y + target_roi.height;
  432 + qDebug() << "target_roi.y: " << target_roi.y << " height: " << target_roi.height;
  433 + qFatal("die");
  434 + }
  435 +
  436 +
326 std::vector<cv::Mat> channels; 437 std::vector<cv::Mat> channels;
327 cv::split(outIm, channels); 438 cv::split(outIm, channels);
328 439
@@ -335,6 +446,7 @@ class AdjacentOverlayTransform : public Transform @@ -335,6 +446,7 @@ class AdjacentOverlayTransform : public Transform
335 } 446 }
336 cv::merge(channels, outIm); 447 cv::merge(channels, outIm);
337 dst.m() = outIm; 448 dst.m() = outIm;
  449 +
338 } 450 }
339 451
340 void init() 452 void init()