void TrackMarker::resetTrack() { Point curCenter; KnobDoublePtr knob = getCenterKnob(); curCenter.x = knob->getValue(0); curCenter.y = knob->getValue(1); EffectInstancePtr effect = getContext()->getNode()->getEffectInstance(); effect->beginChanges(); const KnobsVec& knobs = getKnobs(); for (KnobsVec::const_iterator it = knobs.begin(); it != knobs.end(); ++it) { if (*it != knob) { for (int i = 0; i < (*it)->getDimension(); ++i) { (*it)->resetToDefaultValue(i); } } else { for (int i = 0; i < (*it)->getDimension(); ++i) { (*it)->removeAnimation(ViewSpec::current(), i); } knob->setValue(curCenter.x, ViewSpec::current(), 0); knob->setValue(curCenter.y, ViewSpec::current(), 1); } } effect->endChanges(); removeAllUserKeyframes(); }
void TrackMarker::resetTrack() { Point curCenter; KnobDoublePtr centerKnob = getCenterKnob(); curCenter.x = centerKnob->getValue(); curCenter.y = centerKnob->getValue(DimIdx(1)); const KnobsVec& knobs = getKnobs(); for (KnobsVec::const_iterator it = knobs.begin(); it != knobs.end(); ++it) { if (*it != centerKnob) { (*it)->resetToDefaultValue(DimSpec::all(), ViewSetSpec::all()); } else { (*it)->removeAnimation(ViewSetSpec::all(), DimSpec::all(), eValueChangedReasonUserEdited); std::vector<double> values(2); values[0] = curCenter.x; values[1] = curCenter.y; centerKnob->setValueAcrossDimensions(values); } } removeAnimation(ViewSetSpec::all(), DimSpec::all(), eValueChangedReasonUserEdited); }
void TrackMarker::resetCenter() { TrackerContextPtr context = getContext(); assert(context); NodePtr input = context->getNode()->getInput(0); if (input) { SequenceTime time = input->getApp()->getTimeLine()->currentFrame(); RenderScale scale; scale.x = scale.y = 1; RectD rod; bool isProjectFormat; StatusEnum stat = input->getEffectInstance()->getRegionOfDefinition_public(input->getHashValue(), time, scale, ViewIdx(0), &rod, &isProjectFormat); Point center; center.x = 0; center.y = 0; if (stat == eStatusOK) { center.x = (rod.x1 + rod.x2) / 2.; center.y = (rod.y1 + rod.y2) / 2.; } KnobDoublePtr centerKnob = getCenterKnob(); centerKnob->setValue(center.x, ViewSpec::current(), 0); centerKnob->setValue(center.y, ViewSpec::current(), 1); } }
RectI TrackMarker::getMarkerImageRoI(int time) const { const unsigned int mipmapLevel = 0; Point center, offset; KnobDoublePtr centerKnob = getCenterKnob(); KnobDoublePtr offsetKnob = getOffsetKnob(); center.x = centerKnob->getValueAtTime(time, 0); center.y = centerKnob->getValueAtTime(time, 1); offset.x = offsetKnob->getValueAtTime(time, 0); offset.y = offsetKnob->getValueAtTime(time, 1); RectD roiCanonical; KnobDoublePtr swBl = getSearchWindowBottomLeftKnob(); KnobDoublePtr swTr = getSearchWindowTopRightKnob(); roiCanonical.x1 = swBl->getValueAtTime(time, 0) + center.x + offset.x; roiCanonical.y1 = swBl->getValueAtTime(time, 1) + center.y + offset.y; roiCanonical.x2 = swTr->getValueAtTime(time, 0) + center.x + offset.x; roiCanonical.y2 = swTr->getValueAtTime(time, 1) + center.y + offset.y; RectI roi; NodePtr node = getContext()->getNode(); NodePtr input = node->getInput(0); if (!input) { return RectI(); } roiCanonical.toPixelEnclosing(mipmapLevel, input ? input->getEffectInstance()->getAspectRatio(-1) : 1., &roi); return roi; }
void TrackMarker::clearAnimationAfterTime(TimeValue time) { std::set<double> userKeyframes; getMasterKeyFrameTimes(ViewIdx(0), &userKeyframes); KnobIPtr offsetKnob = getOffsetKnob(); assert(offsetKnob); deleteKnobAnimation(userKeyframes, offsetKnob, eDeleteKnobAnimationAfterTime, time); KnobIPtr centerKnob = getCenterKnob(); assert(centerKnob); deleteKnobAnimation(userKeyframes, centerKnob, eDeleteKnobAnimationAfterTime, time); KnobIPtr errorKnob = getErrorKnob(); assert(errorKnob); deleteKnobAnimation(userKeyframes, errorKnob, eDeleteKnobAnimationAfterTime, time); }
void TrackMarker::clearAnimationAfterTime(int time) { std::set<int> userKeyframes; getUserKeyframes(&userKeyframes); KnobIPtr offsetKnob = getOffsetKnob(); assert(offsetKnob); deleteKnobAnimation(userKeyframes, offsetKnob, eDeleteKnobAnimationAfterTime, time); KnobIPtr centerKnob = getCenterKnob(); assert(centerKnob); deleteKnobAnimation(userKeyframes, centerKnob, eDeleteKnobAnimationAfterTime, time); KnobIPtr errorKnob = getErrorKnob(); assert(errorKnob); deleteKnobAnimation(userKeyframes, errorKnob, eDeleteKnobAnimationAfterTime, time); }
RectD TrackMarker::getMarkerImageRoI(TimeValue time) const { Point center, offset; KnobDoublePtr centerKnob = getCenterKnob(); KnobDoublePtr offsetKnob = getOffsetKnob(); center.x = centerKnob->getValueAtTime(time, DimIdx(0)); center.y = centerKnob->getValueAtTime(time, DimIdx(1)); offset.x = offsetKnob->getValueAtTime(time, DimIdx(0)); offset.y = offsetKnob->getValueAtTime(time, DimIdx(1)); RectD roiCanonical; KnobDoublePtr swBl = getSearchWindowBottomLeftKnob(); KnobDoublePtr swTr = getSearchWindowTopRightKnob(); roiCanonical.x1 = swBl->getValueAtTime(time, DimIdx(0)) + center.x + offset.x; roiCanonical.y1 = swBl->getValueAtTime(time, DimIdx(1)) + center.y + offset.y; roiCanonical.x2 = swTr->getValueAtTime(time, DimIdx(0)) + center.x + offset.x; roiCanonical.y2 = swTr->getValueAtTime(time, DimIdx(1)) + center.y + offset.y; return roiCanonical; }
void TrackMarker::resetCenter() { KnobItemsTablePtr model = getModel(); if (!model) { return; } RectD rod; NodePtr input = model->getNode()->getInput(0); if (!input) { Format f; getApp()->getProject()->getProjectDefaultFormat(&f); rod = f.toCanonicalFormat(); } else { TimeValue time(input->getApp()->getTimeLine()->currentFrame()); RenderScale scale(1.); RectD rod; { GetRegionOfDefinitionResultsPtr results; ActionRetCodeEnum stat = input->getEffectInstance()->getRegionOfDefinition_public(time, scale, ViewIdx(0), &results); if (!isFailureRetCode(stat)) { rod = results->getRoD(); } } Point center; center.x = 0; center.y = 0; center.x = (rod.x1 + rod.x2) / 2.; center.y = (rod.y1 + rod.y2) / 2.; KnobDoublePtr centerKnob = getCenterKnob(); centerKnob->setValue(center.x, ViewSetSpec::all(), DimIdx(0)); centerKnob->setValue(center.y, ViewSetSpec::all(), DimIdx(1)); } }
void TrackMarkerPM::initializeKnobs() { TrackMarker::initializeKnobs(); NodePtr thisNode = getModel()->getNode(); NodePtr node; { CreateNodeArgsPtr args(CreateNodeArgs::create( PLUGINID_OFX_TRACKERPM, NodeCollectionPtr() )); args->setProperty<bool>(kCreateNodeArgsPropVolatile, true); args->setProperty<bool>(kCreateNodeArgsPropNoNodeGUI, true); args->setProperty<std::string>(kCreateNodeArgsPropNodeInitialName, "TrackerPMNode"); node = getApp()->createNode(args); if (!node) { throw std::runtime_error("Couldn't create plug-in " PLUGINID_OFX_TRACKERPM); } if (thisNode) { NodePtr inputNode = thisNode->getInput(0); if (inputNode) { node->connectInput(inputNode, 0); } } trackerNode = node; } KnobItemsTablePtr model = getModel(); EffectInstancePtr effect; if (model) { effect = model->getNode()->getEffectInstance(); } trackPrevButton = getNodeKnob<KnobButton>(node, kTrackerPMParamTrackingPrevious); trackNextButton = getNodeKnob<KnobButton>(node, kTrackerPMParamTrackingNext); KnobDoublePtr center = getNodeKnob<KnobDouble>(node, kTrackerPMParamTrackingCenterPoint); centerKnob = center; // Slave the center knob and unslave when tracking if ( !center->linkTo(getCenterKnob()) ) { throw std::runtime_error("Could not link center"); } KnobDoublePtr offset = getNodeKnob<KnobDouble>(node, kTrackerPMParamTrackingOffset); // Slave the offset knob if ( !offset->linkTo( getOffsetKnob() ) ) { throw std::runtime_error("Could not link offset"); } offsetKnob = offset; // Ref frame is set for each refFrameKnob = getNodeKnob<KnobInt>(node, kTrackerPMParamTrackingReferenceFrame); // Enable reference frame KnobBoolPtr enableRefFrameKnob = getNodeKnob<KnobBool>(node, kTrackerPMParamTrackingEnableReferenceFrame); enableRefFrameKnob->setValue(true); KnobChoicePtr scoreType = getNodeKnob<KnobChoice>(node, kTrackerPMParamScore); if (effect) { #ifdef kTrackerParamPatternMatchingScoreType KnobIPtr modelKnob = effect->getKnobByName(kTrackerParamPatternMatchingScoreType); if (modelKnob) { if ( !scoreType->linkTo(modelKnob) ) { throw std::runtime_error("Could not link scoreType"); } } #endif } scoreTypeKnob = scoreType; KnobDoublePtr correlationScore = getNodeKnob<KnobDouble>(node, kTrackerPMParamTrackingCorrelationScore); correlationScoreKnob = correlationScore; KnobDoublePtr patternBtmLeft = getNodeKnob<KnobDouble>(node, kTrackerPMParamTrackingPatternBoxBtmLeft); patternBtmLeftKnob = patternBtmLeft; // Slave the search window and pattern of the node to the parameters of the marker (void)patternBtmLeft->linkTo(getPatternBtmLeftKnob()); KnobDoublePtr patternTopRight = getNodeKnob<KnobDouble>(node, kTrackerPMParamTrackingPatternBoxTopRight); patternTopRightKnob = patternTopRight; (void)patternTopRight->linkTo(getPatternTopRightKnob()); KnobDoublePtr searchWindowBtmLeft = getNodeKnob<KnobDouble>(node, kTrackerPMParamTrackingSearchBoxBtmLeft); searchWindowBtmLeftKnob = searchWindowBtmLeft; (void)searchWindowBtmLeft->linkTo(getSearchWindowBottomLeftKnob()); KnobDoublePtr searchWindowTopRight = getNodeKnob<KnobDouble>(node, kTrackerPMParamTrackingSearchBoxTopRight); searchWindowTopRightKnob = searchWindowTopRight; (void)searchWindowTopRight->linkTo(getSearchWindowTopRightKnob()); } // TrackMarkerPM::initializeKnobs
bool TrackMarkerPM::trackMarker(bool forward, int refFrame, int frame) { KnobButtonPtr button; if (forward) { button = trackNextButton.lock(); } else { button = trackPrevButton.lock(); } KnobIntPtr refFrameK = refFrameKnob.lock(); refFrameK->setValue(refFrame); // Unslave the center knob since the trackerNode will update it, then update the marker center KnobDoublePtr center = centerKnob.lock(); center->unlink(DimSpec::all(), ViewSetSpec::all(), true); trackerNode->getEffectInstance()->onKnobValueChanged_public(button, eValueChangedReasonUserEdited, TimeValue(frame), ViewIdx(0)); KnobDoublePtr markerCenter = getCenterKnob(); // The TrackerPM plug-in has set a keyframe at the refFrame and frame, copy them bool ret = true; double centerPoint[2]; for (int i = 0; i < center->getNDimensions(); ++i) { { int index = center->getKeyFrameIndex(ViewIdx(0), DimIdx(i), TimeValue(frame)); if (index != -1) { centerPoint[i] = center->getValueAtTime(TimeValue(frame), DimIdx(i)); markerCenter->setValueAtTime(TimeValue(frame), centerPoint[i], ViewSetSpec::all(), DimIdx(i)); } else { // No keyframe at this time: tracking failed ret = false; break; } } { int index = center->getKeyFrameIndex(ViewIdx(0), DimIdx(i), TimeValue(refFrame)); if (index != -1) { double value = center->getValueAtTime(TimeValue(refFrame), DimIdx(i)); markerCenter->setValueAtTime(TimeValue(refFrame), value, ViewSetSpec::all(), DimIdx(i)); } } } // Convert the correlation score of the TrackerPM to the error if (ret) { KnobDoublePtr markerError = getErrorKnob(); KnobDoublePtr correlation = correlationScoreKnob.lock(); { int index = correlation->getKeyFrameIndex(ViewIdx(0), DimIdx(0), TimeValue(frame)); if (index != -1) { // The error is estimated as a percentage of the correlation across the number of pixels in the pattern window KnobDoublePtr pBtmLeft = patternBtmLeftKnob.lock(); KnobDoublePtr pTopRight = patternTopRightKnob.lock(); Point btmLeft, topRight; btmLeft.x = pBtmLeft->getValueAtTime(TimeValue(frame), DimIdx(0)); btmLeft.y = pBtmLeft->getValueAtTime(TimeValue(frame), DimIdx(1)); topRight.x = pTopRight->getValueAtTime(TimeValue(frame), DimIdx(0)); topRight.y = pTopRight->getValueAtTime(TimeValue(frame), DimIdx(1)); double areaPixels = (topRight.x - btmLeft.x) * (topRight.y - btmLeft.y); NodePtr trackerInput = trackerNode->getInput(0); if (trackerInput) { ImagePlaneDesc comps, paireComps; trackerInput->getEffectInstance()->getMetadataComponents(-1, &comps, &paireComps); areaPixels *= comps.getNumComponents(); } double value = correlation->getValueAtTime(TimeValue(frame), DimIdx(0)); // Convert to a percentage if (areaPixels > 0) { value /= areaPixels; } markerError->setValueAtTime(TimeValue(frame), value, ViewSetSpec::all(), DimIdx(0)); } } } if ( !center->linkTo(markerCenter) ) { throw std::runtime_error("Could not link center"); } return ret; } // TrackMarkerPM::trackMarker
void TrackMarkerPM::initializeKnobs() { TrackMarker::initializeKnobs(); NodePtr thisNode = getContext()->getNode(); QObject::connect( getContext().get(), SIGNAL(onNodeInputChanged(int)), this, SLOT(onTrackerNodeInputChanged(int)) ); NodePtr node; { CreateNodeArgs args( PLUGINID_OFX_TRACKERPM, NodeCollectionPtr() ); args.setProperty<bool>(kCreateNodeArgsPropOutOfProject, true); args.setProperty<bool>(kCreateNodeArgsPropNoNodeGUI, true); args.setProperty<std::string>(kCreateNodeArgsPropNodeInitialName, "TrackerPMNode"); node = getContext()->getNode()->getApp()->createNode(args); if (!node) { throw std::runtime_error("Couldn't create plug-in " PLUGINID_OFX_TRACKERPM); } if (thisNode) { NodePtr inputNode = thisNode->getInput(0); if (inputNode) { node->connectInput(inputNode, 0); } } trackerNode = node; } trackPrevButton = getNodeKnob<KnobButton>(node, kTrackerPMParamTrackingPrevious); trackNextButton = getNodeKnob<KnobButton>(node, kTrackerPMParamTrackingNext); KnobDoublePtr center = getNodeKnob<KnobDouble>(node, kTrackerPMParamTrackingCenterPoint); centerKnob = center; // Slave the center knob and unslave when tracking for (int i = 0; i < center->getDimension(); ++i) { center->slaveTo(i, getCenterKnob(), i); } KnobDoublePtr offset = getNodeKnob<KnobDouble>(node, kTrackerPMParamTrackingOffset); // Slave the offset knob for (int i = 0; i < offset->getDimension(); ++i) { offset->slaveTo(i, getOffsetKnob(), i); } offsetKnob = offset; // Ref frame is set for each refFrameKnob = getNodeKnob<KnobInt>(node, kTrackerPMParamTrackingReferenceFrame); // Enable reference frame KnobBoolPtr enableRefFrameKnob = getNodeKnob<KnobBool>(node, kTrackerPMParamTrackingEnableReferenceFrame); enableRefFrameKnob->setValue(true); KnobChoicePtr scoreType = getNodeKnob<KnobChoice>(node, kTrackerPMParamScore); scoreType->slaveTo(0, getContext()->getCorrelationScoreTypeKnob(), 0); scoreTypeKnob = scoreType; KnobDoublePtr correlationScore = getNodeKnob<KnobDouble>(node, kTrackerPMParamTrackingCorrelationScore); correlationScoreKnob = correlationScore; KnobDoublePtr patternBtmLeft = getNodeKnob<KnobDouble>(node, kTrackerPMParamTrackingPatternBoxBtmLeft); patternBtmLeftKnob = patternBtmLeft; // Slave the search window and pattern of the node to the parameters of the marker for (int i = 0; i < patternBtmLeft->getDimension(); ++i) { patternBtmLeft->slaveTo(i, getPatternBtmLeftKnob(), i); } KnobDoublePtr patternTopRight = getNodeKnob<KnobDouble>(node, kTrackerPMParamTrackingPatternBoxTopRight); patternTopRightKnob = patternTopRight; for (int i = 0; i < patternTopRight->getDimension(); ++i) { patternTopRight->slaveTo(i, getPatternTopRightKnob(), i); } KnobDoublePtr searchWindowBtmLeft = getNodeKnob<KnobDouble>(node, kTrackerPMParamTrackingSearchBoxBtmLeft); searchWindowBtmLeftKnob = searchWindowBtmLeft; for (int i = 0; i < searchWindowBtmLeft->getDimension(); ++i) { searchWindowBtmLeft->slaveTo(i, getSearchWindowBottomLeftKnob(), i); } KnobDoublePtr searchWindowTopRight = getNodeKnob<KnobDouble>(node, kTrackerPMParamTrackingSearchBoxTopRight); searchWindowTopRightKnob = searchWindowTopRight; for (int i = 0; i < searchWindowTopRight->getDimension(); ++i) { searchWindowTopRight->slaveTo(i, getSearchWindowTopRightKnob(), i); } } // TrackMarkerPM::initializeKnobs
bool TrackMarkerPM::trackMarker(bool forward, int refFrame, int frame) { KnobButtonPtr button; if (forward) { button = trackNextButton.lock(); } else { button = trackPrevButton.lock(); } KnobIntPtr refFrameK = refFrameKnob.lock(); refFrameK->setValue(refFrame); // Unslave the center knob since the trackerNode will update it, then update the marker center KnobDoublePtr center = centerKnob.lock(); for (int i = 0; i < center->getDimension(); ++i) { center->unSlave(i, true); } trackerNode->getEffectInstance()->onKnobValueChanged_public(button, eValueChangedReasonNatronInternalEdited, frame, ViewIdx(0), true); KnobDoublePtr markerCenter = getCenterKnob(); // The TrackerPM plug-in has set a keyframe at the refFrame and frame, copy them bool ret = true; double centerPoint[2]; for (int i = 0; i < center->getDimension(); ++i) { { int index = center->getKeyFrameIndex(ViewSpec::current(), i, frame); if (index != -1) { centerPoint[i] = center->getValueAtTime(frame, i); markerCenter->setValueAtTime(frame, centerPoint[i], ViewSpec::current(), i); } else { // No keyframe at this time: tracking failed ret = false; break; } } { int index = center->getKeyFrameIndex(ViewSpec::current(), i, refFrame); if (index != -1) { double value = center->getValueAtTime(refFrame, i); markerCenter->setValueAtTime(refFrame, value, ViewSpec::current(), i); } } } // Convert the correlation score of the TrackerPM to the error if (ret) { KnobDoublePtr markerError = getErrorKnob(); KnobDoublePtr correlation = correlationScoreKnob.lock(); { int index = correlation->getKeyFrameIndex(ViewSpec::current(), 0, frame); if (index != -1) { // The error is estimated as a percentage of the correlation across the number of pixels in the pattern window KnobDoublePtr pBtmLeft = patternBtmLeftKnob.lock(); KnobDoublePtr pTopRight = patternTopRightKnob.lock(); Point btmLeft, topRight; btmLeft.x = pBtmLeft->getValueAtTime(frame, 0); btmLeft.y = pBtmLeft->getValueAtTime(frame, 1); topRight.x = pTopRight->getValueAtTime(frame, 0); topRight.y = pTopRight->getValueAtTime(frame, 1); double areaPixels = (topRight.x - btmLeft.x) * (topRight.y - btmLeft.y); NodePtr trackerInput = trackerNode->getInput(0); if (trackerInput) { ImageComponents comps = trackerInput->getEffectInstance()->getComponents(-1); areaPixels *= comps.getNumComponents(); } double value = correlation->getValueAtTime(frame, 0); // Convert to a percentage value /= areaPixels; markerError->setValueAtTime(frame, value, ViewSpec::current(), 0); } } } for (int i = 0; i < center->getDimension(); ++i) { center->slaveTo(i, markerCenter, i); } return ret; } // TrackMarkerPM::trackMarker