egami
C++ Image Processing program
/homes/esi30/DCS339/coursework/src/Processes/automatic_th.cpp
Go to the documentation of this file.
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 }
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends