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 271 void project(const Template &src, Template &dst) const
272 272 {
273 273 dst = src;
  274 +
274 275 if (imgName.isEmpty() || targetName.isEmpty() || !dst.file.contains(imgName) || !dst.file.contains(targetName))
275 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 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 296 // match width with target region
284 297 qreal target_width = target_location.width();
... ... @@ -290,39 +303,137 @@ class AdjacentOverlayTransform : public Transform
290 303  
291 304 cv::resize(im, im, cv::Size(target_width, target_height));
292 305  
  306 + // ROI used to maybe crop the matched image
293 307 cv::Rect clip_roi;
294 308 clip_roi.x = 0;
295 309 clip_roi.y = 0;
296 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 313 int half_width = src.m().cols / 2;
300 314 int out_x = 0;
  315 +
  316 + // place in the source image we will copy the matched image to.
301 317 cv::Rect target_roi;
  318 + bool left_side = false;
  319 + int width_adjust = 0;
302 320 // Place left
303 321 if (target_location.center().rx() > half_width) {
304 322 out_x = target_location.left() - im.cols;
305 323 if (out_x < 0) {
306   - clip_roi.width += out_x;
  324 + width_adjust = abs(out_x);
307 325 out_x = 0;
308 326 }
  327 + left_side = true;
309 328 }
310 329 // place right
311 330 else {
312 331 out_x = target_location.right();
313 332 int high = out_x + im.cols;
314 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 403 target_roi.x = out_x;
319 404 target_roi.width = clip_roi.width;
320 405 target_roi.y = target_location.top();
321 406 target_roi.height = clip_roi.height;
322 407  
  408 +
323 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 437 std::vector<cv::Mat> channels;
327 438 cv::split(outIm, channels);
328 439  
... ... @@ -335,6 +446,7 @@ class AdjacentOverlayTransform : public Transform
335 446 }
336 447 cv::merge(channels, outIm);
337 448 dst.m() = outIm;
  449 +
338 450 }
339 451  
340 452 void init()
... ...