-
Notifications
You must be signed in to change notification settings - Fork 1
/
image.cpp
149 lines (119 loc) · 3.33 KB
/
image.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <iostream>
#include <cmath>
#include <stdexcept>
#include <boost/lexical_cast.hpp>
#include "image.hpp"
namespace instame {
image::image(const std::string& path, int thumbnail_size, int rep_size, bool remove_border) :
m_path(path),
m_pixels_rep(NULL),
m_rep_size(rep_size),
m_thumbnail_size(thumbnail_size),
m_remove_border(remove_border)
{
m_image.read(path);
process_image();
}
image::image(Magick::Image& image, int thumbnail_size, int rep_size, bool remove_border) :
m_image(image),
m_rep_size(rep_size),
m_pixels_rep(NULL),
m_thumbnail_size(thumbnail_size),
m_remove_border(remove_border)
{
process_image();
}
void
image::process_image() {
if (m_remove_border) {
int border = 35;
m_image.crop(Magick::Geometry(m_image.columns() - border * 2,
m_image.rows() - border * 2,
border,
border));
}
m_thumbnail = m_image;
std::string tttt = boost::lexical_cast<std::string>(m_thumbnail_size);
tttt = tttt + "x" + tttt + "!";
Magick::Geometry thumb_geo(tttt.c_str());
m_thumbnail.resize(thumb_geo);
std::string rrrr = boost::lexical_cast<std::string>(m_rep_size);
rrrr = rrrr + "x" + rrrr + "!";
Magick::Geometry image_geo(rrrr);
m_image.resize(image_geo);
m_image.modifyImage();
m_image.type(Magick::TrueColorType);
m_pixels_rep = m_image.getPixels(0, 0, m_rep_size, m_rep_size);
}
double
image::distance(image& image) {
return distance_naive(image);
}
double
image::distance_exclusive(image& img) {
int bad_pixels = 0;
for (int i = 0; i < m_rep_size; ++i) {
for (int j = 0; j < m_rep_size; ++j) {
Magick::ColorRGB pixel_dst = img.get_pixel(i, j);
Magick::ColorRGB pixel_src = get_pixel(i, j);
if (pixel_distance(pixel_dst, pixel_src) > m_threshold) {
bad_pixels++;
}
}
}
return (double)bad_pixels / (double)(m_rep_size * m_rep_size);
}
double
image::distance_mean(image& img) {
double total_distance = 0.0;
for (int i = 0; i < m_rep_size; ++i) {
for (int j = 0; j < m_rep_size; ++j) {
Magick::ColorRGB pixel_dst = img.get_pixel(i, j);
Magick::ColorRGB pixel_src = get_pixel(i, j);
total_distance += pixel_distance(pixel_dst, pixel_src);
}
}
return total_distance / (m_rep_size * m_rep_size);
}
double
image::distance_naive(image& img) {
double total_distance = 0.0;
for (int i = 0; i < m_rep_size; ++i) {
for (int j = 0; j < m_rep_size; ++j) {
Magick::ColorRGB pixel_dst = img.get_pixel(i, j);
Magick::ColorRGB pixel_src = get_pixel(i, j);
total_distance += pixel_distance(pixel_dst, pixel_src);
}
}
return total_distance;
}
void
image::write_representation(const std::string& path) {
m_image.write(path);
}
void
image::write_thumbnail(const std::string& path) {
m_thumbnail.write(path);
}
Magick::ColorRGB
image::get_pixel(int x, int y) {
Magick::Color pixel = m_pixels_rep[m_rep_size * y + x];
Magick::ColorRGB pixel_rgb = pixel;
return pixel_rgb;
}
void
image::set_pixel(int x, int y, const Magick::ColorRGB& color) {
m_pixels_rep[m_rep_size * y + x] = color;
}
inline double
image::pixel_distance(const Magick::ColorRGB& src, const Magick::ColorRGB& dst) const {
double delta_r = src.red() - dst.red();
double delta_g = src.green() - dst.green();
double delta_b = src.blue() - dst.blue();
return sqrt(delta_r * delta_r + delta_g * delta_g + delta_b * delta_b);
}
std::string
image::path() const {
return m_path;
}
} // namespace instame