diff --git a/rtdata/languages/default b/rtdata/languages/default index d12360bba..fe84680a3 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -1378,6 +1378,7 @@ HISTORY_MSG_PERSP_METHOD;Perspective - Method HISTORY_MSG_PERSP_PROJ_ANGLE;Perspective - Recovery HISTORY_MSG_PERSP_PROJ_ROTATE;Perspective - PCA rotation HISTORY_MSG_PERSP_PROJ_SHIFT;Perspective - PCA +HISTORY_MSG_PIXELSHIFT_AVERAGE;PS - Average HISTORY_MSG_PIXELSHIFT_DEMOSAIC;PS - Demosaic method for motion HISTORY_MSG_PREPROCESS_LINEDENOISE_DIRECTION;Line noise filter direction HISTORY_MSG_PREPROCESS_PDAFLINESFILTER;PDAF lines filter @@ -3435,6 +3436,8 @@ TP_RAW_LMMSE_TOOLTIP;Adds gamma (step 1), median (steps 2-4) and refinement (ste TP_RAW_MONO;Mono TP_RAW_NONE;None (Shows sensor pattern) TP_RAW_PIXELSHIFT;Pixel Shift +TP_RAW_PIXELSHIFTAVERAGE;Use average for moving parts +TP_RAW_PIXELSHIFTAVERAGE_TOOLTIP;Use average of all frames instead of selected frame for regions with motion.\nGives motion effect on slow moving (overlapping) objects. TP_RAW_PIXELSHIFTBLUR;Blur motion mask TP_RAW_PIXELSHIFTDMETHOD;Demosaic method for motion TP_RAW_PIXELSHIFTEPERISO;Sensitivity diff --git a/rtengine/pixelshift.cc b/rtengine/pixelshift.cc index ff7be3e40..8088e2e9c 100644 --- a/rtengine/pixelshift.cc +++ b/rtengine/pixelshift.cc @@ -334,7 +334,7 @@ BENCHFUN if(motionDetection) { if(!showOnlyMask) { - if(bayerParams.pixelShiftMedian) { // We need the demosaiced frames for motion correction + if(bayerParams.pixelShiftMedian || bayerParams.pixelShiftAverage) { // We need the demosaiced frames for motion correction if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(procparams::RAWParams::BayerSensor::PSDemosaicMethod::LMMSE)) { lmmse_interpolate_omp(winw, winh, *(rawDataFrames[0]), red, green, blue, bayerParams.lmmse_iterations); } else if (bayerParams.pixelShiftDemosaicMethod == bayerParams.getPSDemosaicMethodString(procparams::RAWParams::BayerSensor::PSDemosaicMethod::AMAZEVNG4)) { @@ -359,22 +359,42 @@ BENCHFUN amaze_demosaic_RT(winx, winy, winw, winh, *(rawDataFrames[i + 1]), redTmp[i], greenTmp[i], blueTmp[i], options.chunkSizeAMAZE, options.measure); } } + if(bayerParams.pixelShiftMedian) { #ifdef _OPENMP - #pragma omp parallel for schedule(dynamic,16) + #pragma omp parallel for schedule(dynamic,16) #endif - for(int i = winy + border; i < winh - border; i++) { - for(int j = winx + border; j < winw - border; j++) { - red[i][j] = median(red[i][j], redTmp[0][i + 1][j], redTmp[1][i + 1][j + 1], redTmp[2][i][j + 1]); - } + for(int i = winy + border; i < winh - border; i++) { + for(int j = winx + border; j < winw - border; j++) { + red[i][j] = median(red[i][j], redTmp[0][i + 1][j], redTmp[1][i + 1][j + 1], redTmp[2][i][j + 1]); + } - for(int j = winx + border; j < winw - border; j++) { - green[i][j] = median(green[i][j], greenTmp[0][i + 1][j], greenTmp[1][i + 1][j + 1], greenTmp[2][i][j + 1]); - } + for(int j = winx + border; j < winw - border; j++) { + green[i][j] = median(green[i][j], greenTmp[0][i + 1][j], greenTmp[1][i + 1][j + 1], greenTmp[2][i][j + 1]); + } - for(int j = winx + border; j < winw - border; j++) { - blue[i][j] = median(blue[i][j], blueTmp[0][i + 1][j], blueTmp[1][i + 1][j + 1], blueTmp[2][i][j + 1]); + for(int j = winx + border; j < winw - border; j++) { + blue[i][j] = median(blue[i][j], blueTmp[0][i + 1][j], blueTmp[1][i + 1][j + 1], blueTmp[2][i][j + 1]); + } + } + } else { +#ifdef _OPENMP + #pragma omp parallel for schedule(dynamic,16) +#endif + + for(int i = winy + border; i < winh - border; i++) { + for(int j = winx + border; j < winw - border; j++) { + red[i][j] = 0.25f * ((red[i][j] + redTmp[0][i + 1][j]) + (redTmp[1][i + 1][j + 1] + redTmp[2][i][j + 1])); + } + + for(int j = winx + border; j < winw - border; j++) { + green[i][j] = 0.25f * ((green[i][j] + greenTmp[0][i + 1][j]) + (greenTmp[1][i + 1][j + 1] + greenTmp[2][i][j + 1])); + } + + for(int j = winx + border; j < winw - border; j++) { + blue[i][j] = 0.25f * ((blue[i][j] + blueTmp[0][i + 1][j]) + (blueTmp[1][i + 1][j + 1] + blueTmp[2][i][j + 1])); + } } } } else { diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 04f71de59..9d6c23db9 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -5051,6 +5051,7 @@ RAWParams::BayerSensor::BayerSensor() : pixelShiftShowMotionMaskOnly(false), pixelShiftHoleFill(true), pixelShiftMedian(false), + pixelShiftAverage(false), pixelShiftGreen(true), pixelShiftBlur(true), pixelShiftSmoothFactor(0.7), @@ -5089,6 +5090,7 @@ bool RAWParams::BayerSensor::operator ==(const BayerSensor& other) const && pixelShiftShowMotionMaskOnly == other.pixelShiftShowMotionMaskOnly && pixelShiftHoleFill == other.pixelShiftHoleFill && pixelShiftMedian == other.pixelShiftMedian + && pixelShiftAverage == other.pixelShiftAverage && pixelShiftGreen == other.pixelShiftGreen && pixelShiftBlur == other.pixelShiftBlur && pixelShiftSmoothFactor == other.pixelShiftSmoothFactor @@ -5112,6 +5114,7 @@ void RAWParams::BayerSensor::setPixelShiftDefaults() pixelShiftSigma = 1.0; pixelShiftHoleFill = true; pixelShiftMedian = false; + pixelShiftAverage = false; pixelShiftGreen = true; pixelShiftBlur = true; pixelShiftSmoothFactor = 0.7; @@ -7005,6 +7008,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftShowMotion, "RAW Bayer", "PixelShiftShowMotion", raw.bayersensor.pixelShiftShowMotion, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftShowMotionMaskOnly, "RAW Bayer", "PixelShiftShowMotionMaskOnly", raw.bayersensor.pixelShiftShowMotionMaskOnly, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftHoleFill, "RAW Bayer", "pixelShiftHoleFill", raw.bayersensor.pixelShiftHoleFill, keyFile); + saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftAverage, "RAW Bayer", "pixelShiftAverage", raw.bayersensor.pixelShiftAverage, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftMedian, "RAW Bayer", "pixelShiftMedian", raw.bayersensor.pixelShiftMedian, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftGreen, "RAW Bayer", "pixelShiftGreen", raw.bayersensor.pixelShiftGreen, keyFile); saveToKeyfile(!pedited || pedited->raw.bayersensor.pixelShiftBlur, "RAW Bayer", "pixelShiftBlur", raw.bayersensor.pixelShiftBlur, keyFile); @@ -9603,6 +9607,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "RAW Bayer", "PixelShiftShowMotionMaskOnly", pedited, raw.bayersensor.pixelShiftShowMotionMaskOnly, pedited->raw.bayersensor.pixelShiftShowMotionMaskOnly); assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftHoleFill", pedited, raw.bayersensor.pixelShiftHoleFill, pedited->raw.bayersensor.pixelShiftHoleFill); assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftMedian", pedited, raw.bayersensor.pixelShiftMedian, pedited->raw.bayersensor.pixelShiftMedian); + assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftAverage", pedited, raw.bayersensor.pixelShiftAverage, pedited->raw.bayersensor.pixelShiftAverage); assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftGreen", pedited, raw.bayersensor.pixelShiftGreen, pedited->raw.bayersensor.pixelShiftGreen); assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftBlur", pedited, raw.bayersensor.pixelShiftBlur, pedited->raw.bayersensor.pixelShiftBlur); assignFromKeyfile(keyFile, "RAW Bayer", "pixelShiftSmoothFactor", pedited, raw.bayersensor.pixelShiftSmoothFactor, pedited->raw.bayersensor.pixelShiftSmooth); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index a4d59ccb7..c9dc2e42f 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -2244,6 +2244,7 @@ struct RAWParams { bool pixelShiftShowMotionMaskOnly; bool pixelShiftHoleFill; bool pixelShiftMedian; + bool pixelShiftAverage; bool pixelShiftGreen; bool pixelShiftBlur; double pixelShiftSmoothFactor; diff --git a/rtgui/bayerprocess.cc b/rtgui/bayerprocess.cc index 6da15951f..4d1657a47 100644 --- a/rtgui/bayerprocess.cc +++ b/rtgui/bayerprocess.cc @@ -39,6 +39,7 @@ BayerProcess::BayerProcess () : EvDemosaicContrast = m->newEvent(DEMOSAIC, "HISTORY_MSG_DUALDEMOSAIC_CONTRAST"); EvDemosaicAutoContrast = m->newEvent(DEMOSAIC, "HISTORY_MSG_DUALDEMOSAIC_AUTO_CONTRAST"); EvDemosaicPixelshiftDemosaicMethod = m->newEvent(DEMOSAIC, "HISTORY_MSG_PIXELSHIFT_DEMOSAIC"); + EvPixelshiftAverage = m->newEvent(DEMOSAIC, "HISTORY_MSG_PIXELSHIFT_AVERAGE"); Gtk::Box* hb1 = Gtk::manage (new Gtk::Box ()); hb1->pack_start (*Gtk::manage (new Gtk::Label ( M("TP_RAW_DMETHOD") + ": ")), Gtk::PACK_SHRINK, 4); @@ -226,7 +227,13 @@ BayerProcess::BayerProcess () : pixelShiftMedian = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTMEDIAN"), multiImage)); pixelShiftMedian->setCheckBoxListener (this); pixelShiftMedian->set_tooltip_text (M("TP_RAW_PIXELSHIFTMEDIAN_TOOLTIP")); + + pixelShiftAverage = Gtk::manage (new CheckBox(M("TP_RAW_PIXELSHIFTAVERAGE"), multiImage)); + pixelShiftAverage->setCheckBoxListener (this); + pixelShiftAverage->set_tooltip_text (M("TP_RAW_PIXELSHIFTAVERAGE_TOOLTIP")); + pixelShiftOptions->pack_start(*pixelShiftMedian); + pixelShiftOptions->pack_start(*pixelShiftAverage); pixelShiftMainVBox->pack_start(*pixelShiftOptions); pixelShiftFrame->add(*pixelShiftMainVBox); @@ -281,6 +288,7 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params } pixelShiftHoleFill->setValue (pp->raw.bayersensor.pixelShiftHoleFill); pixelShiftMedian->setValue (pp->raw.bayersensor.pixelShiftMedian); + pixelShiftAverage->setValue (pp->raw.bayersensor.pixelShiftAverage); pixelShiftGreen->setValue (pp->raw.bayersensor.pixelShiftGreen); pixelShiftBlur->setValue (pp->raw.bayersensor.pixelShiftBlur); pixelShiftSmooth->setValue (pp->raw.bayersensor.pixelShiftSmoothFactor); @@ -314,6 +322,7 @@ void BayerProcess::read(const rtengine::procparams::ProcParams* pp, const Params pixelShiftShowMotionMaskOnly->setEdited (pedited->raw.bayersensor.pixelShiftShowMotionMaskOnly); pixelShiftHoleFill->setEdited (pedited->raw.bayersensor.pixelShiftHoleFill); pixelShiftMedian->setEdited(pedited->raw.bayersensor.pixelShiftMedian); + pixelShiftAverage->setEdited(pedited->raw.bayersensor.pixelShiftAverage); pixelShiftGreen->setEdited (pedited->raw.bayersensor.pixelShiftGreen); pixelShiftBlur->setEdited (pedited->raw.bayersensor.pixelShiftBlur); pixelShiftSmooth->setEditedState ( pedited->raw.bayersensor.pixelShiftSmooth ? Edited : UnEdited); @@ -396,6 +405,7 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe pp->raw.bayersensor.pixelShiftShowMotionMaskOnly = pixelShiftShowMotionMaskOnly->getLastActive (); pp->raw.bayersensor.pixelShiftHoleFill = pixelShiftHoleFill->getLastActive (); pp->raw.bayersensor.pixelShiftMedian = pixelShiftMedian->getLastActive (); + pp->raw.bayersensor.pixelShiftAverage = pixelShiftAverage->getLastActive (); pp->raw.bayersensor.pixelShiftGreen = pixelShiftGreen->getLastActive (); pp->raw.bayersensor.pixelShiftBlur = pixelShiftBlur->getLastActive (); pp->raw.bayersensor.pixelShiftSmoothFactor = pixelShiftSmooth->getValue(); @@ -438,6 +448,7 @@ void BayerProcess::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pe pedited->raw.bayersensor.pixelShiftShowMotionMaskOnly = !pixelShiftShowMotionMaskOnly->get_inconsistent(); pedited->raw.bayersensor.pixelShiftHoleFill = !pixelShiftHoleFill->get_inconsistent(); pedited->raw.bayersensor.pixelShiftMedian = !pixelShiftMedian->get_inconsistent(); + pedited->raw.bayersensor.pixelShiftAverage = !pixelShiftAverage->get_inconsistent(); pedited->raw.bayersensor.pixelShiftGreen = !pixelShiftGreen->get_inconsistent(); pedited->raw.bayersensor.pixelShiftBlur = !pixelShiftBlur->get_inconsistent(); pedited->raw.bayersensor.pixelShiftSmooth = pixelShiftSmooth->getEditedState(); @@ -632,9 +643,19 @@ void BayerProcess::checkBoxToggled (CheckBox* c, CheckValue newval) listener->panelChanged (EvPixelShiftHoleFill, pixelShiftHoleFill->getValueAsStr ()); } } else if (c == pixelShiftMedian) { + if (pixelShiftMedian->getLastActive()) { + pixelShiftAverage->setValue(false); + } if (listener) { listener->panelChanged (EvPixelShiftMedian, pixelShiftMedian->getValueAsStr ()); } + } else if (c == pixelShiftAverage) { + if (pixelShiftAverage->getLastActive()) { + pixelShiftMedian->setValue(false); + } + if (listener) { + listener->panelChanged (EvPixelshiftAverage, pixelShiftAverage->getValueAsStr ()); + } } else if (c == pixelShiftGreen) { if (listener) { listener->panelChanged (EvPixelShiftGreen, pixelShiftGreen->getValueAsStr ()); diff --git a/rtgui/bayerprocess.h b/rtgui/bayerprocess.h index c2af5a987..b9c63e9b2 100644 --- a/rtgui/bayerprocess.h +++ b/rtgui/bayerprocess.h @@ -58,6 +58,7 @@ protected: CheckBox* pixelShiftBlur; CheckBox* pixelShiftHoleFill; CheckBox* pixelShiftMedian; + CheckBox* pixelShiftAverage; CheckBox* pixelShiftEqualBright; CheckBox* pixelShiftEqualBrightChannel; Adjuster* pixelShiftSmooth; @@ -73,6 +74,7 @@ protected: rtengine::ProcEvent EvDemosaicAutoContrast; rtengine::ProcEvent EvDemosaicContrast; rtengine::ProcEvent EvDemosaicPixelshiftDemosaicMethod; + rtengine::ProcEvent EvPixelshiftAverage; public: BayerProcess (); diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index ada149b95..916a166bb 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -487,6 +487,7 @@ void ParamsEdited::set(bool v) raw.bayersensor.pixelShiftShowMotionMaskOnly = v; raw.bayersensor.pixelShiftHoleFill = v; raw.bayersensor.pixelShiftMedian = v; + raw.bayersensor.pixelShiftAverage = v; raw.bayersensor.pixelShiftGreen = v; raw.bayersensor.pixelShiftBlur = v; raw.bayersensor.pixelShiftSmooth = v; @@ -1780,6 +1781,7 @@ void ParamsEdited::initFrom(const std::vector& raw.bayersensor.pixelShiftShowMotionMaskOnly = raw.bayersensor.pixelShiftShowMotionMaskOnly && p.raw.bayersensor.pixelShiftShowMotionMaskOnly == other.raw.bayersensor.pixelShiftShowMotionMaskOnly; raw.bayersensor.pixelShiftHoleFill = raw.bayersensor.pixelShiftHoleFill && p.raw.bayersensor.pixelShiftHoleFill == other.raw.bayersensor.pixelShiftHoleFill; raw.bayersensor.pixelShiftMedian = raw.bayersensor.pixelShiftMedian && p.raw.bayersensor.pixelShiftMedian == other.raw.bayersensor.pixelShiftMedian; + raw.bayersensor.pixelShiftAverage = raw.bayersensor.pixelShiftAverage && p.raw.bayersensor.pixelShiftAverage == other.raw.bayersensor.pixelShiftAverage; raw.bayersensor.pixelShiftGreen = raw.bayersensor.pixelShiftGreen && p.raw.bayersensor.pixelShiftGreen == other.raw.bayersensor.pixelShiftGreen; raw.bayersensor.pixelShiftBlur = raw.bayersensor.pixelShiftBlur && p.raw.bayersensor.pixelShiftBlur == other.raw.bayersensor.pixelShiftBlur; raw.bayersensor.pixelShiftSmooth = raw.bayersensor.pixelShiftSmooth && p.raw.bayersensor.pixelShiftSmoothFactor == other.raw.bayersensor.pixelShiftSmoothFactor; @@ -5950,6 +5952,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.raw.bayersensor.pixelShiftMedian = mods.raw.bayersensor.pixelShiftMedian; } + if (raw.bayersensor.pixelShiftAverage) { + toEdit.raw.bayersensor.pixelShiftAverage = mods.raw.bayersensor.pixelShiftAverage; + } + if (raw.bayersensor.pixelShiftGreen) { toEdit.raw.bayersensor.pixelShiftGreen = mods.raw.bayersensor.pixelShiftGreen; } @@ -6797,7 +6803,7 @@ bool RAWParamsEdited::BayerSensor::isUnchanged() const { return method && border && imageNum && dcbIterations && dcbEnhance && lmmseIterations && dualDemosaicAutoContrast && dualDemosaicContrast /*&& allEnhance*/ && greenEq && pixelShiftMotionCorrectionMethod && pixelShiftEperIso && pixelShiftSigma && pixelShiftShowMotion && pixelShiftShowMotionMaskOnly - && pixelShiftHoleFill && pixelShiftMedian && pixelShiftNonGreenCross && pixelShiftDemosaicMethod && pixelShiftGreen && pixelShiftBlur && pixelShiftSmooth && pixelShiftEqualBright && pixelShiftEqualBrightChannel + && pixelShiftHoleFill && pixelShiftMedian && pixelShiftAverage && pixelShiftNonGreenCross && pixelShiftDemosaicMethod && pixelShiftGreen && pixelShiftBlur && pixelShiftSmooth && pixelShiftEqualBright && pixelShiftEqualBrightChannel && linenoise && linenoiseDirection && pdafLinesFilter && exBlack0 && exBlack1 && exBlack2 && exBlack3 && exTwoGreen; } diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index 87f510e64..da96d8f93 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -1331,6 +1331,7 @@ struct RAWParamsEdited { bool pixelShiftShowMotionMaskOnly; bool pixelShiftHoleFill; bool pixelShiftMedian; + bool pixelShiftAverage; bool pixelShiftGreen; bool pixelShiftBlur; bool pixelShiftSmooth; diff --git a/rtgui/partialpastedlg.cc b/rtgui/partialpastedlg.cc index 9a3399662..b3c49dfd7 100644 --- a/rtgui/partialpastedlg.cc +++ b/rtgui/partialpastedlg.cc @@ -1105,6 +1105,7 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param filterPE.raw.bayersensor.pixelShiftHoleFill = falsePE.raw.bayersensor.pixelShiftHoleFill; filterPE.raw.bayersensor.pixelShiftDemosaicMethod = falsePE.raw.bayersensor.pixelShiftDemosaicMethod; filterPE.raw.bayersensor.pixelShiftMedian = falsePE.raw.bayersensor.pixelShiftMedian; + filterPE.raw.bayersensor.pixelShiftAverage = falsePE.raw.bayersensor.pixelShiftAverage; filterPE.raw.bayersensor.pixelShiftMotionCorrectionMethod = falsePE.raw.bayersensor.pixelShiftMotionCorrectionMethod; filterPE.raw.bayersensor.pixelShiftNonGreenCross = falsePE.raw.bayersensor.pixelShiftNonGreenCross; filterPE.raw.bayersensor.pixelShiftSigma = falsePE.raw.bayersensor.pixelShiftSigma;