diff --git a/openbr/plugins/draw.cpp b/openbr/plugins/draw.cpp index 00f9a8e..5573a1e 100644 --- a/openbr/plugins/draw.cpp +++ b/openbr/plugins/draw.cpp @@ -271,14 +271,27 @@ class AdjacentOverlayTransform : public Transform void project(const Template &src, Template &dst) const { dst = src; + if (imgName.isEmpty() || targetName.isEmpty() || !dst.file.contains(imgName) || !dst.file.contains(targetName)) return; - QString im_name = src.file.get(imgName); + QVariant temp = src.file.value(imgName); + cv::Mat im; + // is this a filename? + if (temp.canConvert()) { + QString im_name = temp.toString(); + Template temp_im; + opener->project(File(im_name), temp_im); + im = temp_im.m(); + } + // a cv::Mat ? + else if (temp.canConvert()) + im = src.file.get(imgName); + else + qDebug() << "Unrecognized property type " << imgName << "for" << src.file.name; + + // Location of detected face in source image QRectF target_location = src.file.get(targetName); - Template temp_im; - opener->project(File(im_name), temp_im); - cv::Mat im = temp_im.m(); // match width with target region qreal target_width = target_location.width(); @@ -290,39 +303,137 @@ class AdjacentOverlayTransform : public Transform cv::resize(im, im, cv::Size(target_width, target_height)); + // ROI used to maybe crop the matched image cv::Rect clip_roi; clip_roi.x = 0; clip_roi.y = 0; clip_roi.width = im.cols; - clip_roi.height= im.rows; + clip_roi.height= im.rows <= dst.m().rows ? im.rows : dst.m().rows; int half_width = src.m().cols / 2; int out_x = 0; + + // place in the source image we will copy the matched image to. cv::Rect target_roi; + bool left_side = false; + int width_adjust = 0; // Place left if (target_location.center().rx() > half_width) { out_x = target_location.left() - im.cols; if (out_x < 0) { - clip_roi.width += out_x; + width_adjust = abs(out_x); out_x = 0; } + left_side = true; } // place right else { out_x = target_location.right(); int high = out_x + im.cols; if (high >= src.m().cols) { - clip_roi.width -= high - src.m().cols + 1; + width_adjust = abs(high - src.m().cols + 1); } } + + cv::Mat outIm; + if (width_adjust) + { + outIm.create(dst.m().rows, dst.m().cols + width_adjust, CV_8UC3); + memset(outIm.data, 127, outIm.rows * outIm.cols * outIm.channels()); + + Rect temp; + + if (left_side) + temp = Rect(abs(width_adjust), 0, dst.m().cols, dst.m().rows); + + else + temp = Rect(0, 0, dst.m().cols, dst.m().rows); + + dst.m().copyTo(outIm(temp)); + + } + else + outIm = dst.m(); + + if (clip_roi.height + target_location.top() >= outIm.rows) + { + clip_roi.height -= abs(outIm.rows - (clip_roi.height + target_location.top() )); + } + if (clip_roi.x + clip_roi.width >= im.cols) { + clip_roi.width -= abs(im.cols - (clip_roi.x + clip_roi.width + 1)); + if (clip_roi.width < 0) + clip_roi.width = 1; + } + + if (clip_roi.y + clip_roi.height >= im.rows) { + clip_roi.height -= abs(im.rows - (clip_roi.y + clip_roi.height + 1)); + } + if (clip_roi.x < 0) + clip_roi.x = 0; + if (clip_roi.y < 0) + clip_roi.y = 0; + + if (clip_roi.height < 0) + clip_roi.height = 0; + + if (clip_roi.width < 0) + clip_roi.width = 0; + + + if (clip_roi.y + clip_roi.height >= im.rows) + { + qDebug() << "Bad clip y" << clip_roi.y + clip_roi.height << im.rows; + } + if (clip_roi.x + clip_roi.width >= im.cols) + { + qDebug() << "Bad clip x" << clip_roi.x + clip_roi.width << im.cols; + } + + if (clip_roi.y < 0 || clip_roi.height < 0) + { + qDebug() << "bad clip y, low" << clip_roi.y << clip_roi.height; + qFatal("die"); + } + if (clip_roi.x < 0 || clip_roi.width < 0) + { + qDebug() << "bad clip x, low" << clip_roi.x << clip_roi.width; + qFatal("die"); + } + target_roi.x = out_x; target_roi.width = clip_roi.width; target_roi.y = target_location.top(); target_roi.height = clip_roi.height; + im = im(clip_roi); - cv::Mat outIm = dst.m(); + if (target_roi.x < 0 || target_roi.x >= outIm.cols) + { + qDebug() << "Bad xdim in targetROI!" << target_roi.x << " out im x: " << outIm.cols; + qFatal("die"); + } + + if (target_roi.x + target_roi.width < 0 || (target_roi.x + target_roi.width) >= outIm.cols) + { + qDebug() << "Bad xdim in targetROI!" << target_roi.x + target_roi.width; + qFatal("die"); + } + + if (target_roi.y < 0 || target_roi.y >= outIm.rows) + { + qDebug() << "Bad ydim in targetROI!" << target_roi.y; + qFatal("die"); + } + + if ((target_roi.y + target_roi.height) < 0 || (target_roi.y + target_roi.height) > outIm.rows) + { + qDebug() << "Bad ydim in targetROI!" << target_roi.y + target_roi.height; + qDebug() << "target_roi.y: " << target_roi.y << " height: " << target_roi.height; + qFatal("die"); + } + + std::vector channels; cv::split(outIm, channels); @@ -335,6 +446,7 @@ class AdjacentOverlayTransform : public Transform } cv::merge(channels, outIm); dst.m() = outIm; + } void init() diff --git a/openbr/plugins/meta.cpp b/openbr/plugins/meta.cpp index c713c98..a30809f 100644 --- a/openbr/plugins/meta.cpp +++ b/openbr/plugins/meta.cpp @@ -502,6 +502,11 @@ private: else trainable = false; } + bool timeVarying() const + { + return transform->timeVarying(); + } + void train(const TemplateList &data) { if (QFileInfo(getFileName()).exists()) @@ -527,6 +532,21 @@ private: transform->project(src, dst); } + void projectUpdate(const Template &src, Template &dst) + { + transform->projectUpdate(src, dst); + } + + void projectUpdate(const TemplateList &src, TemplateList &dst) + { + transform->projectUpdate(src, dst); + } + + void finalize(TemplateList & output) + { + transform->finalize(output); + } + QString getFileName() const { if (QFileInfo(baseName).exists()) return baseName;