Skip to content

Commit

Permalink
Added support of automatic hot pixels removal
Browse files Browse the repository at this point in the history
for raw and mono stream types
  • Loading branch information
artyom-beilis committed Jul 14, 2024
1 parent f61b496 commit bb97973
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 25 deletions.
1 change: 1 addition & 0 deletions include/data_items.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ namespace ols {
bool derotate = false; /// enable auto derote for AZ mount
bool derotate_mirror = false; /// inverse direction for mirror image
bool remove_gradient = false; // remove linear gradient
bool remove_hot_pixels = false; // remove hot pixels
double ra=-1,de=-1,lat=-1,lon=-1; /// object data an

Filters filters;
Expand Down
106 changes: 106 additions & 0 deletions include/hot_removal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#pragma once
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/core/hal/intrin.hpp>

namespace ols {
#ifdef USE_CV_SIMD
template<typename VType>
struct VTraits;

template<>
struct VTraits<uint16_t> {
typedef cv::v_uint16x8 vtype;
};

template<>
struct VTraits<uint8_t> {
typedef cv::v_uint8x16 vtype;
};

template<typename VType,typename UInt,int Delta>
static std::pair<VType,VType> load3x3v(UInt *r_prev,UInt *r_curr,UInt *r_next)
{
VType max_v,min_v,v;
max_v = min_v = cv::v_load(r_prev + 0);
v = cv::v_load(r_prev + Delta); max_v=cv::v_max(max_v,v); min_v=cv::v_min(min_v,v);
v = cv::v_load(r_prev + 2*Delta); max_v=cv::v_max(max_v,v); min_v=cv::v_min(min_v,v);
v = cv::v_load(r_next + 0); max_v=cv::v_max(max_v,v); min_v=cv::v_min(min_v,v);
v = cv::v_load(r_next + Delta); max_v=cv::v_max(max_v,v); min_v=cv::v_min(min_v,v);
v = cv::v_load(r_next + 2*Delta); max_v=cv::v_max(max_v,v); min_v=cv::v_min(min_v,v);
v = cv::v_load(r_curr + 0); max_v=cv::v_max(max_v,v); min_v=cv::v_min(min_v,v);
v = cv::v_load(r_curr + 2*Delta); max_v=cv::v_max(max_v,v); min_v=cv::v_min(min_v,v);
return std::make_pair(min_v,max_v);
}
#endif
template<typename UInt,int Delta>
std::pair<UInt,UInt> load3x3(UInt *r_prev,UInt *r_curr,UInt *r_next)
{
UInt max_v,min_v,v;
max_v = min_v = r_prev[0];
v = r_prev[Delta]; max_v=std::max(max_v,v); min_v=std::min(min_v,v);
v = r_prev[2*Delta]; max_v=std::max(max_v,v); min_v=std::min(min_v,v);
v = r_next[0]; max_v=std::max(max_v,v); min_v=std::min(min_v,v);
v = r_next[Delta]; max_v=std::max(max_v,v); min_v=std::min(min_v,v);
v = r_next[2*Delta]; max_v=std::max(max_v,v); min_v=std::min(min_v,v);
v = r_curr[0]; max_v=std::max(max_v,v); min_v=std::min(min_v,v);
v = r_curr[2*Delta]; max_v=std::max(max_v,v); min_v=std::min(min_v,v);
return std::make_pair(min_v,max_v);
}
template<typename UInt,int Delta>
void remove_hot_pixels_impl(cv::Mat &in,cv::Mat &out)
{
int step = in.cols;
for(int r=Delta;r<in.rows-Delta;r++) {
int c=Delta;
UInt *p = (UInt*)in.data + r*step + c;
UInt *o = (UInt*)out.data + r*step + c;
#ifdef USE_CV_SIMD
typedef typename VTraits<UInt>::vtype vtype;
constexpr int elems = 16/sizeof(UInt);
int N = (in.cols - 2*Delta) / elems;
for(int i=0;i<N;i++) {
auto range = load3x3v<vtype,UInt,Delta>(p-Delta*step - Delta,p-Delta,p+Delta*step-Delta);
vtype px = cv::v_load(p);
vtype diff = px - range.second;
vtype grad = range.second - range.first;
auto mask = (px > range.second) & (diff > grad);
vtype res = cv::v_select(mask,range.second,px);
cv::v_store(o,res);

p+= elems;
o+= elems;
c+= elems;
}
#endif
for(;c<in.cols-Delta;c++,p++,o++) {
auto range = load3x3<UInt,Delta>(p-Delta*step - Delta,p-Delta,p+Delta*step-Delta);
UInt px = p[0];
if(px > range.second) {
UInt diff = px - range.second;
if(diff > range.second - range.first)
o[0] = range.second;
}
}
}
}
cv::Mat remove_hot_pixels(cv::Mat in,bool mono=false)
{
if(in.elemSize1() > 2 || in.channels()!=1)
return in;
cv::Mat res = in.clone();
if(in.elemSize1() == 1) {
if(mono)
remove_hot_pixels_impl<uint8_t,1>(in,res);
else
remove_hot_pixels_impl<uint8_t,2>(in,res);
}
else if(in.elemSize1() == 2) {
if(mono)
remove_hot_pixels_impl<uint16_t,1>(in,res);
else
remove_hot_pixels_impl<uint16_t,2>(in,res);
}
return res;
}
}
1 change: 1 addition & 0 deletions include/stacker_ctl_app.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ namespace ols {

cmd->synthetic_exposure_mpl = content_.get("synthetic_exposure_mpl",cmd->synthetic_exposure_mpl);
cmd->remove_gradient = content_.get("remove_gradient",cmd->remove_gradient);
cmd->remove_hot_pixels = content_.get("remove_hot_pixels",cmd->remove_hot_pixels);
cmd->derotate_mirror = content_.get("image_flip",cmd->derotate_mirror);
cmd->derotate = content_.get("field_derotation",cmd->derotate);
cmd->rollback_on_pause = content_.get("rollback_on_pause",cmd->rollback_on_pause);
Expand Down
20 changes: 1 addition & 19 deletions src/android_camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,25 +302,7 @@ namespace ols {
sort_formats();
return formats_;
}
/*
std::pair<cv::Mat,CamBayerType> to_rgb(std::pair<cv::Mat,CamBayerType> const &raw)
{
cv::Mat rgb,result;
cv::Mat bayer = raw.first;
switch(raw.second) {
case bayer_rg: cv::cvtColor(bayer,rgb,cv::COLOR_BayerBG2BGR); break; // COLOR_BayerRGGB2BGR = COLOR_BayerBG2BGR
case bayer_gr: cv::cvtColor(bayer,rgb,cv::COLOR_BayerGB2BGR); break; // COLOR_BayerGRBG2BGR = COLOR_BayerGB2BGR
case bayer_bg: cv::cvtColor(bayer,rgb,cv::COLOR_BayerRG2BGR); break; // COLOR_BayerBGGR2BGR = COLOR_BayerRG2BGR
case bayer_gb: cv::cvtColor(bayer,rgb,cv::COLOR_BayerGR2BGR); break; // COLOR_BayerGBRG2BGR = COLOR_BayerGR2BGR
default:
throw std::runtime_error("Invalid bayer patter");
}
if(format_.bin == 1)
return std::make_pair(rgb,bayer_na);
cv::resize(rgb,result,cv::Size(format_.width,format_.height),0.0,0.0,cv::INTER_AREA);
return std::make_pair(result,bayer_na);
}
*/

void mono_bin2(unsigned char *p,int stride,int rows,int cols,uint16_t *out)
{
for(int r=0,r2=0;r<rows;r++,r2+=2,p+= 2 * stride) {
Expand Down
1 change: 1 addition & 0 deletions src/debug_save_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ namespace ols {
v["derotate"] = ctl->derotate;
v["derotate_mirror"] = ctl->derotate_mirror;
v["remove_gradient"] = ctl->remove_gradient;
v["remove_hot_pixels"] = ctl->remove_hot_pixels;
v["ra"] = ctl->ra;
v["de"] = ctl->de;
v["lat"] = ctl->lat;
Expand Down
23 changes: 17 additions & 6 deletions src/video_generator.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "video_generator.h"
#include "live_stretch.h"
#include "hot_removal.h"
#include <booster/log.h>
#include <booster/posix_time.h>
#include <opencv2/imgcodecs.hpp>
Expand Down Expand Up @@ -143,12 +144,16 @@ namespace ols {
case stream_raw16:
{
cv::Mat bayer(frame->format.height,frame->format.width,(bpp==1 ? CV_8UC1 : CV_16UC1),frame->source_frame->data());
cv::Mat rgb;
cv::Mat desp,rgb;
if(remove_hot_pixels_)
desp = remove_hot_pixels(bayer,false);
else
desp = bayer;
switch(frame->bayer) {
case bayer_rg: cv::cvtColor(bayer,rgb,cv::COLOR_BayerBG2BGR); break; // COLOR_BayerRGGB2BGR = COLOR_BayerBG2BGR
case bayer_gr: cv::cvtColor(bayer,rgb,cv::COLOR_BayerGB2BGR); break; // COLOR_BayerGRBG2BGR = COLOR_BayerGB2BGR
case bayer_bg: cv::cvtColor(bayer,rgb,cv::COLOR_BayerRG2BGR); break; // COLOR_BayerBGGR2BGR = COLOR_BayerRG2BGR
case bayer_gb: cv::cvtColor(bayer,rgb,cv::COLOR_BayerGR2BGR); break; // COLOR_BayerGBRG2BGR = COLOR_BayerGR2BGR
case bayer_rg: cv::cvtColor(desp,rgb,cv::COLOR_BayerBG2BGR); break; // COLOR_BayerRGGB2BGR = COLOR_BayerBG2BGR
case bayer_gr: cv::cvtColor(desp,rgb,cv::COLOR_BayerGB2BGR); break; // COLOR_BayerGRBG2BGR = COLOR_BayerGB2BGR
case bayer_bg: cv::cvtColor(desp,rgb,cv::COLOR_BayerRG2BGR); break; // COLOR_BayerBGGR2BGR = COLOR_BayerRG2BGR
case bayer_gb: cv::cvtColor(desp,rgb,cv::COLOR_BayerGR2BGR); break; // COLOR_BayerGBRG2BGR = COLOR_BayerGR2BGR
default:
BOOSTER_ERROR("stacker") << "Invalid bayer patter";
}
Expand All @@ -161,8 +166,11 @@ namespace ols {
case stream_mono16:
{
cv::Mat mono(frame->format.height,frame->format.width,(bpp==1 ? CV_8UC1 : CV_16UC1),frame->source_frame->data());
cv::Mat desp = mono;
if(remove_hot_pixels_)
desp = remove_hot_pixels(mono,true);
frame->frame_dr = (bpp==1 ? 255 : 65535);
handle_jpeg_stack(frame,mono,true);
handle_jpeg_stack(frame,desp,true);
frame->raw = mono;
}
break;
Expand Down Expand Up @@ -207,6 +215,7 @@ namespace ols {
switch(ctl_ptr->op) {
case StackerControl::ctl_init:
stacking_active_ = true;
remove_hot_pixels_ = ctl_ptr->remove_hot_pixels;
stacking_in_process_ = true;
debug_active_ = ctl_ptr->save_inputs;
break;
Expand All @@ -221,6 +230,7 @@ namespace ols {
case StackerControl::ctl_cancel:
stacking_active_ = false;
stacking_in_process_ = false;
remove_hot_pixels_ = false;
break;
case StackerControl::ctl_save:
case StackerControl::ctl_update:
Expand Down Expand Up @@ -256,6 +266,7 @@ namespace ols {
bool stacking_active_ = false;
bool stacking_in_process_ = false;
bool debug_active_ = false;
bool remove_hot_pixels_ = false;
bool live_auto_stretch_ = true;
float cached_factor_ = -1;
booster::ptime cached_factor_updated_;
Expand Down
7 changes: 7 additions & 0 deletions test/offline_sim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <fstream>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include "hot_removal.h"


namespace ols {
Expand Down Expand Up @@ -86,6 +87,11 @@ namespace ols {
if(ext == "tiff") {
img = load_tiff(path);
dr = (1ll << (8*img.elemSize1())) - 1;
if(cfg_.mono || bayer_ != bayer_na) {
if(cfg_.remove_hot_pixels){
img = remove_hot_pixels(img);
}
}
if(bayer_ != bayer_na) {
cv::Mat rgb;
switch(bayer_) {
Expand Down Expand Up @@ -142,6 +148,7 @@ namespace ols {
cfg.derotate = v.get<bool>("derotate");
cfg.derotate_mirror = v.get<bool>("derotate_mirror");
cfg.remove_gradient = v.get<bool>("remove_gradient",false);
cfg.remove_hot_pixels = v.get<bool>("remove_hot_pixels",false);
cfg.ra = v.get<double>("ra");
cfg.de = v.get<double>("de");
cfg.lat = v.get<double>("lat");
Expand Down
1 change: 1 addition & 0 deletions www-data/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
<tr class="dso_config stack_opt" ><td>Exposure Mpl.</td><td><input class="saved_input" id="stack_synthetic_exposure_mpl" type="number" min="1" max="50" value="1"></td><td>&nbsp;</td></tr>
<tr class="dso_config stack_opt" ><td>Derotate</td><td><input class="saved_input" id="stack_field_derotation" type="checkbox" ></td><td>&nbsp;</td></tr>
<tr class="dso_config stack_opt" ><td>Derotate Mirror</td><td><input class="saved_input" id="stack_image_flip" type="checkbox" ></td><td>&nbsp;</td></tr>
<tr class="dso_config calib_config stack_opt" ><td>Remove Hot Pixels</td><td><input class="saved_input" id="stack_remove_hot_pixels" type="checkbox" ></td><td>&nbsp;</td></tr>
<tr class="dso_config stack_opt" ><td>Remove Gradient</td><td><input class="saved_input" id="stack_remove_gradient" type="checkbox" ></td><td>&nbsp;</td></tr>
<tr class="dso_config stack_opt" ><td>Remove Satellites</td><td><input class="saved_input" id="stack_remove_satellites" type="checkbox" ></td><td>&nbsp;</td></tr>
<tr class="dso_config stack_opt" ><td>Target</td><td>RA:<input class="val_input" id="stack_ra" type="text" ></td><td>DE:<input class="val_input" id="stack_de" type="text" ></td></tr>
Expand Down
3 changes: 3 additions & 0 deletions www-data/media/js/code.js
Original file line number Diff line number Diff line change
Expand Up @@ -1442,6 +1442,7 @@ function startStack()
}
var ra=null,de=null,lat=null,lon=null,synthetic_exposure_mpl=1;
var field_derotation=false,image_flip=false,remove_satellites=false,remove_gradient=false;
var remove_hot_pixels=getBVal('remove_hot_pixels');
if(type == 'dso') {
ra=parseRA(getVal("ra"));
de=parseDEC(getVal("de"));
Expand All @@ -1462,6 +1463,7 @@ function startStack()
};
if(type != 'calibration') {
if(type == 'planetary') {
remove_hot_pixels=false;
filters.remove_first = getBVal('filters_remove_first');
}
filters.min_stat_size = parseInt(getVal('filters_min_stat_size'));
Expand Down Expand Up @@ -1519,6 +1521,7 @@ function startStack()
image_flip: image_flip,
remove_satellites: remove_satellites,
remove_gradient: remove_gradient,
remove_hot_pixels: remove_hot_pixels,
rollback_on_pause: rollback_on_pause,
auto_stretch: getBVal("auto_stretch"),
stretch_low: g_stretch.cut,
Expand Down

0 comments on commit bb97973

Please sign in to comment.