Commit 3a91295e authored by Joachim's avatar Joachim
Browse files

Merge branch 'master' of https://github.com/davisking/dlib

parents 22164e5d 75f66582
......@@ -7,6 +7,7 @@
#include "tensor.h"
#include "cuda_errors.h"
#include "cuda_data_ptr.h"
namespace dlib
{
......@@ -26,6 +27,14 @@ namespace dlib
curand_generator(unsigned long long seed);
~curand_generator();
void fill (
cuda_data_ptr<unsigned int>& data
);
/*!
ensures
- Fills data with random 32-bit unsigned integers.
!*/
void fill_gaussian (
tensor& data,
float mean = 0,
......
......@@ -1606,6 +1606,12 @@ namespace dlib
deserialize(item.mask, in);
}
void clean(
)
{
mask.clear();
}
friend std::ostream& operator<<(std::ostream& out, const dropout_& item)
{
out << "dropout\t ("
......@@ -1886,14 +1892,17 @@ namespace dlib
friend void to_xml(const affine_& item, std::ostream& out)
{
out << "<affine";
if (item.mode==CONV_MODE)
out << " mode='conv'";
out << "<affine_con>\n";
else
out << " mode='fc'";
out << ">\n";
out << "<affine_fc>\n";
out << mat(item.params);
out << "</affine>\n";
if (item.mode==CONV_MODE)
out << "</affine_con>\n";
else
out << "</affine_fc>\n";
}
private:
......
......@@ -358,6 +358,20 @@ namespace dlib
input_tensor_to_output_tensor().
!*/
void clean (
);
/*!
Implementing this function is optional. If you don't need it then you don't
have to provide a clean(). But if you do provide it then it must behave as
follows:
ensures
- calling clean() Causes this object to forget about everything except its
parameters. This is useful if your layer caches information between
forward and backward passes and you want to clean out that cache
information before saving the network to disk.
!*/
};
std::ostream& operator<<(std::ostream& out, const EXAMPLE_COMPUTATIONAL_LAYER_& item);
......
......@@ -412,6 +412,16 @@ namespace dlib
overlaps_nms = find_tight_overlap_tester(temp);
// Relax the non-max-suppression a little so that it doesn't accidentally make
// it impossible for the detector to output boxes matching the training data.
// This could be a problem with the tightest possible nms test since there is
// some small variability in how boxes get positioned between the training data
// and the coordinate system used by the detector when it runs. So relaxing it
// here takes care of that.
double relax_amount = 0.10;
auto iou_thresh = std::min(1.0, overlaps_nms.get_iou_thresh()+relax_amount);
auto percent_covered_thresh = std::min(1.0, overlaps_nms.get_percent_covered_thresh()+relax_amount);
overlaps_nms = test_box_overlap(iou_thresh, percent_covered_thresh);
}
};
......
......@@ -135,6 +135,54 @@ namespace dlib { namespace tt
#endif
}
// ----------------------------------------------------------------------------------------
void exp (
tensor& dest,
const tensor& src
)
{
DLIB_CASSERT(dest.size() == src.size());
#ifdef DLIB_USE_CUDA
cuda::exp(dest,src);
#else
dest = exp(mat(src));
#endif
}
// ----------------------------------------------------------------------------------------
void log (
tensor& dest,
const tensor& src
)
{
DLIB_CASSERT(dest.size() == src.size());
#ifdef DLIB_USE_CUDA
cuda::log(dest,src);
#else
dest = log(mat(src));
#endif
}
// ----------------------------------------------------------------------------------------
void log10 (
tensor& dest,
const tensor& src
)
{
DLIB_CASSERT(dest.size() == src.size());
#ifdef DLIB_USE_CUDA
cuda::log10(dest,src);
#else
dest = log10(mat(src));
#endif
}
// ----------------------------------------------------------------------------------------
void gemm (
......
......@@ -98,6 +98,45 @@ namespace dlib { namespace tt
out = beta*out + scale_rows(mat(m1) - scale_rows(mat(m2),mat(v1)), mat(v2));
!*/
// ----------------------------------------------------------------------------------------
void exp (
tensor& dest,
const tensor& src
);
/*!
requires
- dest.size() == src.size()
ensures
- performs: dest = exp(mat(src))
!*/
// ----------------------------------------------------------------------------------------
void log (
tensor& dest,
const tensor& src
);
/*!
requires
- dest.size() == src.size()
ensures
- performs: dest = log(mat(src))
!*/
// ----------------------------------------------------------------------------------------
void log10 (
tensor& dest,
const tensor& src
);
/*!
requires
- dest.size() == src.size()
ensures
- performs: dest = log10(mat(src))
!*/
// ----------------------------------------------------------------------------------------
void gemm (
......@@ -1386,27 +1425,28 @@ namespace dlib { namespace tt
resizable_tensor accum_buffer;
};
// ----------------------------------------------------------------------------------------
void copy_tensor(
tensor& dest,
size_t dest_k_offset,
const tensor& src,
size_t src_k_offset,
size_t count_k
);
/*!
requires
- dest.nc() == src.nc()
- dest.nr() == src.nr()
- dest.num_samples() == src.num_samples()
- dest.k() - dest_k_offset >= count_k
- src.k() - src_k_offset >= count_k
- is_same_object(dest,src) == false
ensures
- performs: dest[i, k + dest_k_offset, r, c] = src[i, k + src_k_offset, r, c], where k in [0..count_k]
Copies content of each sample from src in to corresponding place of sample at dest.
!*/
// ----------------------------------------------------------------------------------------
void copy_tensor(
tensor& dest,
size_t dest_k_offset,
const tensor& src,
size_t src_k_offset,
size_t count_k
);
/*!
requires
- dest.nc() == src.nc()
- dest.nr() == src.nr()
- dest.num_samples() == src.num_samples()
- dest.k() - dest_k_offset >= count_k
- src.k() - src_k_offset >= count_k
- is_same_object(dest,src) == false
ensures
- performs: dest[i, k + dest_k_offset, r, c] = src[i, k + src_k_offset, r, c], where k in [0..count_k]
Copies content of each sample from src in to corresponding place of sample at dest.
!*/
// ----------------------------------------------------------------------------------------
......
......@@ -713,7 +713,7 @@ namespace dlib
// We can't do this outside the loop because the tensors that get
// averaged need to be allocated to their devices before we call set()
// so that the averagers can determine how best to average them.
if (averagers.size() == 0)
if (averagers.size() == 0 || sync_file_reloaded)
{
averagers = std::vector<tt::multi_device_tensor_averager>(net_type::num_computational_layers);
// setup the averagers to point to the tensors in the networks.
......@@ -736,6 +736,8 @@ namespace dlib
if (temp[0]->size() != 0)
averagers[i].set(temp);
}
sync_file_reloaded = false;
}
......@@ -855,6 +857,7 @@ namespace dlib
prob_loss_increasing_thresh_max_value = 0.99999;
prob_loss_increasing_thresh = prob_loss_increasing_thresh_default_value;
updated_net_since_last_sync = false;
sync_file_reloaded = false;
start();
}
......@@ -979,6 +982,7 @@ namespace dlib
{
std::ifstream fin(sync_filename, std::ios::binary);
deserialize(*this, fin);
sync_file_reloaded = true;
if (verbose)
std::cout << "Loss has been increasing, reloading saved state from " << sync_filename << std::endl;
}
......@@ -1230,6 +1234,7 @@ namespace dlib
double prob_loss_increasing_thresh;
std::atomic<bool> updated_net_since_last_sync;
bool sync_file_reloaded;
};
// ----------------------------------------------------------------------------------------
......
......@@ -6,6 +6,7 @@
#include "core.h"
#include "utilities_abstract.h"
#include "../geometry.h"
#include <fstream>
namespace dlib
{
......@@ -103,9 +104,22 @@ namespace dlib
std::ostream& out
)
{
auto old_precision = out.precision(9);
out << "<net>\n";
visit_layers(net, impl::visitor_net_to_xml(out));
out << "</net>\n";
// restore the original stream precision.
out.precision(old_precision);
}
template <typename net_type>
void net_to_xml (
const net_type& net,
const std::string& filename
)
{
std::ofstream fout(filename);
net_to_xml(net, fout);
}
// ----------------------------------------------------------------------------------------
......
......@@ -56,6 +56,21 @@ namespace dlib
stream.
!*/
template <typename net_type>
void net_to_xml (
const net_type& net,
const std::string& filename
);
/*!
requires
- net_type is an object of type add_layer, add_loss_layer, add_skip_layer, or
add_tag_layer.
- All layers in the net must provide to_xml() functions.
ensures
- This function is just like the above net_to_xml(), except it writes to a file
rather than an ostream.
!*/
// ----------------------------------------------------------------------------------------
template <typename net_type>
......
......@@ -441,6 +441,30 @@ namespace dlib
return shrink_rect(rect, -width, -height);
}
inline drectangle set_rect_area (
const drectangle& rect,
double area
)
{
DLIB_ASSERT(area >= 0, "drectangle can't have a negative area.");
if (area == 0)
return drectangle(dcenter(rect));
if (rect.area() == 0)
{
// In this case we will make the output rectangle a square with the requested
// area.
double scale = std::sqrt(area);
return centered_drect(rect, scale, scale);
}
else
{
double scale = std::sqrt(area/rect.area());
return centered_drect(rect, rect.width()*scale, rect.height()*scale);
}
}
inline drectangle set_aspect_ratio (
const drectangle& rect,
double ratio
......
......@@ -585,6 +585,23 @@ namespace dlib
(i.e. grows the given drectangle by expanding its border)
!*/
// ----------------------------------------------------------------------------------------
drectangle set_rect_area (
const drectangle& rect,
double area
);
/*!
requires
- area >= 0
ensures
- Returns a rectangle R such that:
- center(R) == center(rect)
- R has the same aspect ratio as rect. If rect.area() == 0 then the
returned rect has a 1:1 aspect ratio.
- R.area() == area
!*/
// ----------------------------------------------------------------------------------------
drectangle set_aspect_ratio (
......
......@@ -726,6 +726,29 @@ namespace dlib
return rectangle(x, y, x+rect.width()-1, y+rect.height()-1);
}
// ----------------------------------------------------------------------------------------
inline rectangle set_rect_area (
const rectangle& rect,
unsigned long area
)
{
DLIB_ASSERT(area > 0);
if (rect.area() == 0)
{
// In this case we will make the output rectangle a square with the requested
// area.
unsigned long scale = std::round(std::sqrt(area));
return centered_rect(rect, scale, scale);
}
else
{
double scale = std::sqrt(area/(double)rect.area());
return centered_rect(rect, (long)std::round(rect.width()*scale), (long)std::round(rect.height()*scale));
}
}
// ----------------------------------------------------------------------------------------
inline rectangle set_aspect_ratio (
......
......@@ -487,6 +487,23 @@ namespace dlib
and height)
!*/
// ----------------------------------------------------------------------------------------
inline rectangle set_rect_area (
const rectangle& rect,
unsigned long area
);
/*!
requires
- area > 0
ensures
- Returns a rectangle R such that:
- center(R) == center(rect)
- R has the same aspect ratio as rect. If rect.area() == 0 then the
returned rect has a 1:1 aspect ratio.
- R.area() == area
!*/
// ----------------------------------------------------------------------------------------
inline rectangle set_aspect_ratio (
......
......@@ -1284,8 +1284,11 @@ namespace std
Define std::less<vector<T,3> > so that you can use vectors in the associative containers.
!*/
template<typename T>
struct less<dlib::vector<T,3> > : public binary_function<dlib::vector<T,3> ,dlib::vector<T,3> ,bool>
struct less<dlib::vector<T,3> >
{
typedef dlib::vector<T, 3> first_argument_type;
typedef dlib::vector<T, 3> second_argument_type;
typedef bool result_type;
inline bool operator() (const dlib::vector<T,3> & a, const dlib::vector<T,3> & b) const
{
if (a.x() < b.x()) return true;
......@@ -1302,8 +1305,11 @@ namespace std
Define std::less<vector<T,2> > so that you can use vector<T,2>s in the associative containers.
!*/
template<typename T>
struct less<dlib::vector<T,2> > : public binary_function<dlib::vector<T,2> ,dlib::vector<T,2> ,bool>
struct less<dlib::vector<T,2> >
{
typedef dlib::vector<T, 2> first_argument_type;
typedef dlib::vector<T, 2> second_argument_type;
typedef bool result_type;
inline bool operator() (const dlib::vector<T,2> & a, const dlib::vector<T,2> & b) const
{
if (a.x() < b.x()) return true;
......
......@@ -3,12 +3,13 @@
#ifndef DLIB_GRAPH_KERNEl_1_
#define DLIB_GRAPH_KERNEl_1_
#include <memory>
#include <vector>
#include "../serialize.h"
#include "../noncopyable.h"
#include "../std_allocator.h"
#include "../smart_pointers.h"
#include "../algs.h"
#include <vector>
#include "graph_kernel_abstract.h"
#include "../is_kind.h"
......@@ -291,16 +292,16 @@ namespace dlib
private:
friend class graph_kernel_1;
typedef std_allocator<node_type*,mem_manager> alloc_type;
typedef std_allocator<shared_ptr<E>,mem_manager> alloc_edge_type;
typedef std_allocator<std::shared_ptr<E>,mem_manager> alloc_edge_type;
std::vector<node_type*,alloc_type> neighbors;
std::vector<shared_ptr<E>,alloc_edge_type> edges;
std::vector<std::shared_ptr<E>,alloc_edge_type> edges;
unsigned long idx;
};
private:
typedef std_allocator<shared_ptr<node_type>,mem_manager> alloc_type;
typedef std::vector<shared_ptr<node_type>, alloc_type> vector_type;
typedef std_allocator<std::shared_ptr<node_type>,mem_manager> alloc_type;
typedef std::vector<std::shared_ptr<node_type>, alloc_type> vector_type;
vector_type nodes;
};
......@@ -506,7 +507,7 @@ namespace dlib
n1.neighbors.push_back(&n2);
shared_ptr<E> e(new E);
std::shared_ptr<E> e(new E);
n1.edges.push_back(e);
// don't add this twice if this is an edge from node_index1 back to itself
......@@ -571,7 +572,7 @@ namespace dlib
{
try
{
shared_ptr<node_type> n(new node_type);
std::shared_ptr<node_type> n(new node_type);
n->idx = nodes.size();
nodes.push_back(n);
return n->idx;
......
......@@ -162,9 +162,9 @@ namespace dlib
g.set_label(sink_node, SINK_CUT);
// used to indicate "no parent"
const unsigned long nil = g.number_of_nodes();
const unsigned long no_parent = g.number_of_nodes();
parent.assign(g.number_of_nodes(), nil);
parent.assign(g.number_of_nodes(), no_parent);
time = 1;
dist.assign(g.number_of_nodes(), 0);
......@@ -194,14 +194,14 @@ namespace dlib
private:
unsigned long distance_to_origin (
const unsigned long nil,
const unsigned long no_parent,
unsigned long p,
unsigned long
) const
{
unsigned long start = p;
unsigned long count = 0;
while (p != nil)
while (p != no_parent)
{
if (ts[p] == time)
{
......@@ -237,7 +237,7 @@ namespace dlib
typedef typename flow_graph::in_edge_iterator in_edge_iterator;
// used to indicate "no parent"
const unsigned long nil = g.number_of_nodes();
const unsigned long no_parent = g.number_of_nodes();
while (orphans.size() > 0)
{
......@@ -260,7 +260,7 @@ namespace dlib
if (g.get_label(id) != label_p || g.get_flow(q) <= 0 )
continue;
unsigned long temp = distance_to_origin(nil, id,source);
unsigned long temp = distance_to_origin(no_parent, id,source);
if (temp < best_dist)
{
best_dist = temp;
......@@ -276,7 +276,7 @@ namespace dlib
}
// if we didn't find a parent for p
if (parent[p] == nil)
if (parent[p] == no_parent)
{
for(in_edge_iterator q = begin; q != end; ++q)
{
......@@ -290,7 +290,7 @@ namespace dlib
if (parent[id] == p)
{
parent[id] = nil;
parent[id] = no_parent;
orphans.push_back(id);
}
}
......@@ -309,7 +309,7 @@ namespace dlib
if (g.get_label(id) != label_p || g.get_flow(q) <= 0)
continue;
unsigned long temp = distance_to_origin(nil, id,sink);
unsigned long temp = distance_to_origin(no_parent, id,sink);
if (temp < best_dist)
{
......@@ -326,7 +326,7 @@ namespace dlib
}
// if we didn't find a parent for p
if (parent[p] == nil)
if (parent[p] == no_parent)
{
for(out_edge_iterator q = begin; q != end; ++q)
{
......@@ -340,7 +340,7 @@ namespace dlib
if (parent[id] == p)
{
parent[id] = nil;
parent[id] = no_parent;
orphans.push_back(id);
}
}
......@@ -366,7 +366,7 @@ namespace dlib
typedef typename flow_graph::edge_type edge_type;
// used to indicate "no parent"
const unsigned long nil = g.number_of_nodes();
const unsigned long no_parent = g.number_of_nodes();
unsigned long s = source_side;
unsigned long t = sink_side;
......@@ -414,7 +414,7 @@ namespace dlib
g.adjust_flow(t,s, min_cap);
if (g.get_flow(s,t) <= 0)
{
parent[t] = nil;
parent[t] = no_parent;
orphans.push_back(t);
}
......@@ -429,7 +429,7 @@ namespace dlib
g.adjust_flow(t,s, min_cap);
if (g.get_flow(s,t) <= 0)
{
parent[s] = nil;
parent[s] = no_parent;
orphans.push_back(s);
}
s = t;
......
......@@ -17,16 +17,17 @@
#pragma comment (lib, "imm32.lib")
#endif
#include <cmath>
#include <memory>
#include <sstream>
#include <vector>
#include "../threads.h"
#include "../assert.h"
#include "../queue.h"
#include "../sync_extension.h"
#include "../queue.h"
#include "../logger.h"
#include <cmath>
#include <vector>
namespace dlib
{
......@@ -63,9 +64,9 @@ namespace dlib
// ----------------------------------------------------------------------------------------
const shared_ptr_thread_safe<dlib::mutex>& global_mutex()
const std::shared_ptr<dlib::mutex>& global_mutex()
{
static shared_ptr_thread_safe<dlib::mutex> m(new dlib::mutex);
static std::shared_ptr<dlib::mutex> m(new dlib::mutex);
return m;
}
......@@ -118,7 +119,7 @@ namespace dlib
// processing.
thread_id_type event_thread_id;
shared_ptr_thread_safe<dlib::mutex> reference_to_global_mutex;
std::shared_ptr<dlib::mutex> reference_to_global_mutex;
event_handler_thread(
) :
......@@ -288,10 +289,10 @@ namespace dlib
struct call_global_mutex { call_global_mutex() { global_mutex(); } };
static call_global_mutex call_global_mutex_instance;
const shared_ptr_thread_safe<event_handler_thread>& global_data()
const std::shared_ptr<event_handler_thread>& global_data()
{
auto_mutex M(*global_mutex());
static shared_ptr_thread_safe<event_handler_thread> p;
static std::shared_ptr<event_handler_thread> p;
if (p.get() == 0)
{
p.reset(new event_handler_thread());
......@@ -671,7 +672,7 @@ namespace dlib
SetThreadPriority(hand,THREAD_PRIORITY_ABOVE_NORMAL);
CloseHandle(hand);
shared_ptr_thread_safe<event_handler_thread> globals(global_data());
std::shared_ptr<event_handler_thread> globals(global_data());
window_table_type& window_table = globals->window_table;
HWND& helper_window = globals->helper_window;
......@@ -1465,7 +1466,7 @@ namespace dlib
!*/
{
using namespace gui_core_kernel_1_globals;
shared_ptr_thread_safe<event_handler_thread> globals(global_data());
std::shared_ptr<event_handler_thread> globals(global_data());
// if we are running in the event handling thread then just call
// CreateWindow directly
if (get_thread_id() == globals->event_thread_id)
......@@ -2071,7 +2072,7 @@ namespace dlib
using namespace gui_core_kernel_1_globals;
using namespace std;
shared_ptr_thread_safe<event_handler_thread> globals(global_data());
std::shared_ptr<event_handler_thread> globals(global_data());
if (OpenClipboard(globals->helper_window))
{
......@@ -2138,7 +2139,7 @@ namespace dlib
{
using namespace gui_core_kernel_1_globals;
using namespace std;
shared_ptr_thread_safe<event_handler_thread> globals(global_data());
std::shared_ptr<event_handler_thread> globals(global_data());
auto_mutex M(globals->window_table.get_mutex());
if (OpenClipboard(globals->helper_window))
......
......@@ -11,7 +11,9 @@
#error "DLIB_NO_GUI_SUPPORT is defined so you can't use the GUI code. Turn DLIB_NO_GUI_SUPPORT off if you want to use it."
#endif
#include <memory>
#include <string>
#include "../windows_magic.h"
......@@ -39,8 +41,6 @@
#include "../queue.h"
#include "../pixel.h"
#include "../unicode.h"
#include "../smart_pointers_thread_safe.h"
namespace dlib
{
......@@ -169,7 +169,7 @@ namespace dlib
class base_window
{
friend LRESULT CALLBACK gui_core_kernel_1_globals::WndProc (HWND, UINT, WPARAM, LPARAM);
shared_ptr_thread_safe<gui_core_kernel_1_globals::event_handler_thread> globals;
std::shared_ptr<gui_core_kernel_1_globals::event_handler_thread> globals;
HWND hwnd;
DWORD style;
......
......@@ -8,24 +8,25 @@
#include "gui_core_kernel_2.h"
#include <cmath>
#include <cstring>
#include <iostream>
#include <vector>
#include <set>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/Xlocale.h>
#include <X11/XKBlib.h>
#include <poll.h>
#include <iostream>
#include "../assert.h"
#include "../queue.h"
#include <cstring>
#include <cmath>
#include <X11/Xatom.h>
#include "../sync_extension.h"
#include "../logger.h"
#include <vector>
#include <set>
#include "../smart_pointers_thread_safe.h"
namespace dlib
{
......@@ -49,9 +50,9 @@ namespace dlib
// ----------------------------------------------------------------------------------------
const shared_ptr_thread_safe<dlib::mutex>& global_mutex()
const std::shared_ptr<dlib::mutex>& global_mutex()
{
static shared_ptr_thread_safe<dlib::mutex> m(new dlib::mutex);
static std::shared_ptr<dlib::mutex> m(new dlib::mutex);
return m;
}
......@@ -95,7 +96,7 @@ namespace dlib
queue_of_user_events user_events;
queue_of_user_events user_events_temp;
shared_ptr_thread_safe<dlib::mutex> reference_to_global_mutex;
std::shared_ptr<dlib::mutex> reference_to_global_mutex;
event_handler_thread(
) :
......@@ -315,7 +316,7 @@ namespace dlib
Time last_click_time;
XIC xic;
XFontSet fs;
shared_ptr_thread_safe<event_handler_thread> globals;
std::shared_ptr<event_handler_thread> globals;
};
// Do all this just to make sure global_mutex() is initialized at program start
......@@ -324,10 +325,10 @@ namespace dlib
struct call_global_mutex { call_global_mutex() { global_mutex(); } };
static call_global_mutex call_global_mutex_instance;
const shared_ptr_thread_safe<event_handler_thread>& global_data()
const std::shared_ptr<event_handler_thread>& global_data()
{
auto_mutex M(*global_mutex());
static shared_ptr_thread_safe<event_handler_thread> p;
static std::shared_ptr<event_handler_thread> p;
if (p.get() == 0)
p.reset(new event_handler_thread());
return p;
......@@ -1356,7 +1357,7 @@ namespace dlib
{
using namespace gui_core_kernel_2_globals;
shared_ptr_thread_safe<event_handler_thread> globals(global_data());
std::shared_ptr<event_handler_thread> globals(global_data());
auto_mutex M(globals->window_table.get_mutex());
globals->clipboard = str.c_str();
......@@ -1405,7 +1406,7 @@ namespace dlib
)
{
using namespace gui_core_kernel_2_globals;
shared_ptr_thread_safe<event_handler_thread> globals(global_data());
std::shared_ptr<event_handler_thread> globals(global_data());
auto_mutex M(globals->window_table.get_mutex());
str.clear();
......@@ -1495,7 +1496,7 @@ namespace dlib
void*
)
{
shared_ptr_thread_safe<event_handler_thread> globals(global_data());
std::shared_ptr<event_handler_thread> globals(global_data());
auto_mutex M(globals->window_table.get_mutex());
globals->user_events.lock();
......@@ -1536,7 +1537,7 @@ namespace dlib
e.p = p;
e.i = i;
{
shared_ptr_thread_safe<event_handler_thread> globals(global_data());
std::shared_ptr<event_handler_thread> globals(global_data());
auto_mutex M(globals->user_events.get_mutex());
globals->user_events.enqueue(e);
......
......@@ -3,10 +3,11 @@
#ifndef DLIB_BASE_WIDGETs_CPP_
#define DLIB_BASE_WIDGETs_CPP_
#include "base_widgets.h"
#include "../assert.h"
#include <iostream>
#include <memory>
#include "base_widgets.h"
#include "../assert.h"
namespace dlib
{
......@@ -133,7 +134,7 @@ namespace dlib
void button::
set_main_font (
const shared_ptr_thread_safe<font>& f
const std::shared_ptr<font>& f
)
{
auto_mutex M(m);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment