egami
C++ Image Processing program
|
00001 #include <algorithm> 00002 #include <sstream> 00003 #include <tuple> 00004 #include <memory> 00005 #include <string> 00006 00007 #include <gtkmm/image.h> 00008 #include <gtkmm/dialog.h> 00009 #include <gtkmm/entry.h> 00010 #include <gtkmm/label.h> 00011 #include <gtkmm/enums.h> 00012 #include <gtkmm/stock.h> 00013 00014 #include "../display_unit.hpp" 00015 #include "../processing_page.hpp" 00016 #include "../processing_unit.hpp" 00017 #include "../utils.hpp" 00018 00019 namespace{ 00020 class Config: public Gtk::Dialog { 00021 public: 00022 Config(): tt("Epsilon:") { 00023 set_resizable(false); 00024 00025 bt.set_text("0.1"); 00026 get_vbox()->pack_start(tt); 00027 get_vbox()->pack_start(bt); 00028 00029 add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK); 00030 add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); 00031 00032 show_all_children(); 00033 } 00034 00035 double epsilon() const { 00036 std::stringstream ss; 00037 ss << bt.get_text(); 00038 double v; 00039 if(ss >> v) 00040 return v; 00041 else 00042 throw std::runtime_error("Not a number"); 00043 } 00044 private: 00045 Gtk::Label tt; 00046 Gtk::Entry bt; 00047 }; 00048 00049 typedef std::tuple<unsigned char, unsigned char, unsigned char> Th_l; 00050 typedef std::pair<std::tuple<double, double, double>,std::tuple<double, double, double>> Ob_m; 00051 00052 Ob_m compute_means(const Image *img, Th_l thresholds){ 00053 unsigned ros=0, gos=0, bos=0, rbs=0, gbs=0, bbs=0; 00054 unsigned ron=0, gon=0, bon=0, rbn=0, gbn=0, bbn=0; 00055 00056 for(Image::const_iterator it=img->begin(); it!=img->end(); ++it){ 00057 (it->r>std::get<0>(thresholds)?ros:rbs)+=it->r; 00058 (it->g>std::get<1>(thresholds)?gos:gbs)+=it->g; 00059 (it->b>std::get<2>(thresholds)?bos:bbs)+=it->b; 00060 (it->r>std::get<0>(thresholds)?ron:rbn)++; 00061 (it->g>std::get<1>(thresholds)?gon:gbn)++; 00062 (it->b>std::get<2>(thresholds)?bon:bbn)++; 00063 } 00064 00065 return Ob_m(std::tuple<double,double,double>(ros/static_cast<double>(ron), gos/static_cast<double>(gon), bos/static_cast<double>(bon)), 00066 std::tuple<double,double,double>(rbs/static_cast<double>(rbn), gbs/static_cast<double>(gbn), bbs/static_cast<double>(bbn))); 00067 } 00068 00069 Display_unit* impl(const Image_unit *in){ 00070 Config config; 00071 if(config.run()!=Gtk::RESPONSE_OK) 00072 return nullptr; 00073 config.hide(); 00074 double epsilon=config.epsilon(); 00075 00076 Th_l threshold, old_th; 00077 00078 double vr=0, vg=0, vb=0; 00079 vr+=(*in)[0][0].r; vg+=(*in)[0][0].g; vb+=(*in)[0][0].b; 00080 vr+=(*in)[in->height()-1][0].r; vg+=(*in)[in->height()-1][0].g; vb+=(*in)[in->height()-1][0].b; 00081 vr+=(*in)[0][in->width()-1].r; vg+=(*in)[0][in->width()-1].g; vb+=(*in)[0][in->width()-1].b; 00082 vr+=(*in)[in->height()-1][in->width()-1].r; vg+=(*in)[in->height()-1][in->width()-1].g; vb+=(*in)[in->height()-1][in->width()-1].b; 00083 00084 std::get<0>(threshold)=vr/4; 00085 std::get<1>(threshold)=vg/4; 00086 std::get<2>(threshold)=vb/4; 00087 00088 do{ 00089 old_th=threshold; 00090 Ob_m m=compute_means(in, threshold); 00091 std::get<0>(threshold)=(std::get<0>(m.first)+std::get<0>(m.second))/2; 00092 std::get<1>(threshold)=(std::get<1>(m.first)+std::get<1>(m.second))/2; 00093 std::get<2>(threshold)=(std::get<2>(m.first)+std::get<2>(m.second))/2; 00094 } while( std::abs(std::get<0>(threshold)-std::get<0>(old_th))>epsilon 00095 || std::abs(std::get<1>(threshold)-std::get<1>(old_th))>epsilon 00096 || std::abs(std::get<2>(threshold)-std::get<2>(old_th))>epsilon); 00097 00098 Image_unit *out(new Image_unit(*in)); 00099 00100 for(Image_unit::iterator it=out->begin(); it!=out->end(); ++it) 00101 *it={ it->r>std::get<0>(threshold)?255:0, it->g>std::get<1>(threshold)?255:0, it->b>std::get<2>(threshold)?255:0 }; 00102 00103 return out; 00104 } 00105 } 00106 00107 namespace Processes{ 00108 void automatic_th(){ 00109 Gtk::Image icon(cmake_install_prefix+std::string("/share/egami/icons/automatic_th.png")); 00110 std::shared_ptr<Processing_unit> pu(new Processing_unit(Processing(&impl), "Automatic", icon, false)); 00111 Processing_page::add_unit_to_page("Threshold", pu); 00112 } 00113 }