Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Olena
pylene
Commits
a606c4d7
Commit
a606c4d7
authored
Jan 16, 2020
by
Edwin Carlinet
Browse files
Merge branch 'development/clean-legacy-maxtree' into development/maxtrees
parents
0fa63169
dfca5836
Pipeline
#16017
passed with stages
in 20 minutes and 24 seconds
Changes
26
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
apps/qcm/Makefile
deleted
100644 → 0
View file @
0fa63169
override
CXXFLAGS
+=
-I
../..
-std
=
c++11
-W
-Wall
LDLIBS
=
-lfreeimage
-lboost_program_options
-ltbb
apps/qcm/qcm.cpp
deleted
100644 → 0
View file @
0fa63169
#include <mln/accu/accumulators/sum.hpp>
#include <mln/core/algorithm/accumulate.hpp>
#include <mln/core/algorithm/copy.hpp>
#include <mln/core/algorithm/transform.hpp>
#include <mln/core/colors.hpp>
#include <mln/core/image/image2d.hpp>
#include <mln/io/imread.hpp>
#include <mln/io/imsave.hpp>
#include <boost/program_options.hpp>
#include <mln/core/image/morphers/casted_image.hpp>
#include <mln/core/win2d.hpp>
#include <mln/morpho/structural/opening.hpp>
namespace
mln
{
static
const
rect2d
qcmbox
=
make_rectangle2d
(
15
,
41
);
static
constexpr
float
qcmboxvdist
=
50.2
;
static
constexpr
int
qcmboxhdist
=
60
;
static
constexpr
int
qcmcolhdist
=
481
;
static
constexpr
point2d
pref
=
{
168
,
2389
};
static
constexpr
char
REPA
=
0x01
;
static
constexpr
char
REPB
=
0x02
;
static
constexpr
char
REPC
=
0x04
;
static
constexpr
char
REPD
=
0x08
;
static
constexpr
char
REPE
=
0x10
;
static
constexpr
char
REPALL
=
0x1F
;
static
unsigned
detection_threshold
=
200
;
image2d
<
rgb8
>
imdebug
;
image2d
<
bool
>
transpose
(
const
image2d
<
bool
>&
x
)
{
box2d
b1
=
x
.
domain
();
box2d
b2
=
{{
b1
.
pmin
[
1
],
b1
.
pmin
[
0
]},
{
b1
.
pmax
[
1
],
b1
.
pmax
[
0
]}};
image2d
<
bool
>
out
(
b2
);
mln_foreach
(
auto
pxin
,
x
.
pixels
())
{
point2d
p
=
pxin
.
point
();
out
.
at
(
p
[
1
],
p
[
0
])
=
pxin
.
val
();
}
return
out
;
}
point2d
detect_offset
(
const
image2d
<
uint8
>&
f
)
{
mln_entering
(
"Offset detection"
);
// rect2d se = make_rectangle2d(21, 51);
box2d
dom
=
{{
125
,
2300
},
{
250
,
2470
}};
image2d
<
bool
>
bin
(
dom
);
copy
((
f
<
180
)
|
dom
,
bin
);
// auto markers = morpho::opening(f, se);
rect2d
se
=
make_rectangle2d
(
21
,
49
);
bin
=
morpho
::
structural
::
opening
(
bin
,
se
);
// auto sub = bin | dom;
mln_foreach
(
auto
px
,
bin
.
pixels
())
if
(
px
.
val
())
{
mln_exiting
();
return
px
.
point
();
}
std
::
cerr
<<
"Marker not found"
<<
std
::
endl
;
std
::
exit
(
1
);
}
template
<
class
I
>
bool
is_plain
(
const
I
&
f
,
point2d
p
)
{
int
count
=
accumulate
(
f
|
qcmbox
(
p
),
accu
::
features
::
sum
<>
());
if
(
count
>
detection_threshold
)
{
for
(
int
i
=
p
[
1
]
-
20
;
i
<=
(
p
[
1
]
+
20
);
++
i
)
{
imdebug
.
at
(
p
[
0
]
-
8
,
i
)
=
rgb8
{
255
,
0
,
0
};
imdebug
.
at
(
p
[
0
]
-
7
,
i
)
=
rgb8
{
255
,
0
,
0
};
imdebug
.
at
(
p
[
0
]
+
7
,
i
)
=
rgb8
{
255
,
0
,
0
};
imdebug
.
at
(
p
[
0
]
+
8
,
i
)
=
rgb8
{
255
,
0
,
0
};
}
}
// std::cout << p << ":" << count << std::endl;
return
count
>
detection_threshold
;
}
template
<
class
I
>
char
detect_question
(
const
I
&
bin
,
point2d
pos
)
{
char
response1
=
0
;
char
response2
=
0
;
point2d
p
=
pos
;
for
(
int
i
=
0
;
i
<
5
;
++
i
,
p
[
1
]
+=
qcmboxhdist
)
if
(
is_plain
(
bin
,
p
))
response1
|=
(
1
<<
i
);
p
=
pos
;
p
[
0
]
+=
qcmboxvdist
;
for
(
int
i
=
0
;
i
<
5
;
++
i
,
p
[
1
]
+=
qcmboxhdist
)
if
(
is_plain
(
bin
,
p
))
response2
|=
(
1
<<
i
);
if
(
response2
==
REPALL
)
return
0
;
else
if
(
response2
)
return
response2
;
else
if
(
response1
and
response1
!=
REPALL
)
return
response1
;
else
return
0
;
}
void
detect_all
(
const
image2d
<
uint8
>&
f
,
point2d
offset
=
{
0
,
0
})
{
mln_entering
(
"Detection des cases"
);
auto
bin
=
f
<
200
;
rect2d
se
=
make_rectangle2d
(
15
,
40
);
// Login
{
point2d
plogin
=
point2d
{
228
,
1895
}
+
offset
;
point2df
p
=
plogin
;
for
(
int
j
=
0
;
j
<
6
;
++
j
,
p
[
1
]
+=
qcmboxhdist
)
{
p
[
0
]
=
plogin
[
0
];
for
(
int
i
=
0
;
i
<
26
;
++
i
,
p
[
0
]
+=
qcmboxvdist
)
{
if
(
is_plain
(
bin
,
p
))
{
std
::
cout
<<
(
char
)(
'a'
+
i
);
break
;
}
}
}
std
::
cout
<<
"-"
;
p
[
1
]
+=
qcmboxhdist
;
p
[
0
]
=
plogin
[
0
];
for
(
int
i
=
0
;
i
<
26
;
++
i
,
p
[
0
]
+=
qcmboxvdist
)
{
if
(
is_plain
(
bin
,
p
))
{
std
::
cout
<<
(
char
)(
'a'
+
i
);
break
;
}
}
std
::
cout
<<
std
::
endl
;
}
// Les questions
{
point2d
p0
=
point2d
{
1734
,
156
}
+
offset
;
point2df
p
=
p0
;
for
(
int
j
=
0
;
j
<
5
;
++
j
,
p
[
1
]
+=
qcmcolhdist
)
{
p
[
0
]
=
p0
[
0
];
for
(
int
i
=
0
;
i
<
10
;
++
i
,
p
[
0
]
+=
2
*
qcmboxvdist
)
{
char
res
=
detect_question
(
bin
,
p
);
// std::cout << (j*10 + i + 1) << " ";
for
(
int
k
=
0
;
k
<
5
;
++
k
)
if
(
res
&
(
1
<<
k
))
std
::
cout
<<
(
char
)(
'a'
+
k
);
std
::
cout
<<
std
::
endl
;
}
}
}
mln_exiting
();
}
}
int
main
(
int
argc
,
char
**
argv
)
{
using
namespace
mln
;
namespace
po
=
boost
::
program_options
;
po
::
options_description
desc
(
"Allowed options"
);
desc
.
add_options
()(
"help"
,
"produce help message"
)(
"threshold,t"
,
po
::
value
<
unsigned
>
(
&
detection_threshold
)
->
default_value
(
200
),
"Set threshold detection"
);
po
::
options_description
desc2
(
""
);
desc2
.
add_options
()(
"input"
,
po
::
value
<
std
::
string
>
()
->
required
(),
"input image"
)(
"output"
,
po
::
value
<
std
::
string
>
()
->
required
(),
"output image"
);
po
::
positional_options_description
pd
;
pd
.
add
(
"input"
,
1
);
pd
.
add
(
"output"
,
1
);
desc2
.
add
(
desc
);
po
::
variables_map
vm
;
po
::
store
(
po
::
command_line_parser
(
argc
,
argv
).
options
(
desc2
).
positional
(
pd
).
run
(),
vm
);
try
{
po
::
notify
(
vm
);
}
catch
(...)
{
std
::
cout
<<
"Usage: "
<<
argv
[
0
]
<<
" input output
\n
"
"Les images doivent être en 200dpi
\n
"
<<
desc
<<
"
\n
"
;
return
1
;
}
if
(
vm
.
count
(
"help"
))
{
std
::
cout
<<
desc
<<
"
\n
"
;
return
1
;
}
image2d
<
uint8
>
f
;
{
mln_entering
(
"Conversion B&W"
)
image2d
<
rgb8
>
ima
;
io
::
imread
(
vm
[
"input"
].
as
<
std
::
string
>
(),
ima
);
f
=
transform
(
ima
,
[](
const
rgb8
&
v
)
->
uint8
{
return
sum
(
v
)
/
3
;
});
imdebug
=
ima
;
copy
(
f
,
imdebug
);
mln_exiting
();
}
point2d
ref
=
detect_offset
(
f
);
point2d
offset
=
ref
-
pref
;
detect_all
(
f
,
offset
);
io
::
imsave
(
imdebug
,
vm
[
"output"
].
as
<
std
::
string
>
());
// std::cout << "Ref: " << ref << std::endl;
// std::cout << "Offset: " << offset << std::endl;
}
apps/qcm/qcm.py
deleted
100755 → 0
View file @
0fa63169
#!/usr/bin/python
#coding: utf-8
import
sys
import
matplotlib.pyplot
as
plt
import
math
#Usage: ./qcm.py input.txt input.tiff output.tiff
assert
(
len
(
sys
.
argv
)
>
3
)
# Import note
# f = open(sys.argv[1])
# Rrep = [ line.strip() for line in f ]
# f.close()
Rrep
=
[
"bc"
,
"c"
,
"d"
,
"a"
,
"b"
,
"d"
,
"b"
,
"c"
,
"abd"
,
"abc"
,
"bd"
,
"abd"
,
"b"
,
"a"
,
"b"
]
# Import student
f
=
open
(
sys
.
argv
[
1
])
login
=
f
.
readline
().
strip
()
Srep
=
[
line
.
strip
()
for
line
in
f
]
f
.
close
()
#print Srep, len(Rrep)
# Get the note
notes
=
[
1
if
u
==
v
else
0
if
v
==
""
else
-
.
25
for
u
,
v
in
zip
(
Rrep
,
Srep
)
]
# Print
note
=
20.0
*
sum
(
notes
)
/
len
(
notes
)
note
=
math
.
ceil
(
note
*
2
)
/
2
# arrondi à 0.5
print
"%s,%.01f,%s"
%
(
login
,
note
,
sys
.
argv
[
2
])
###############################
## Write the image ###
###############################
img
=
plt
.
imread
(
sys
.
argv
[
2
])
ypixels
,
xpixels
,
_
=
img
.
shape
dpi
=
200.
xinch
=
xpixels
/
dpi
yinch
=
ypixels
/
dpi
fig
=
plt
.
figure
(
figsize
=
(
xinch
,
yinch
))
ax
=
plt
.
axes
([
0.
,
0.
,
1.
,
1.
],
frameon
=
False
,
xticks
=
[],
yticks
=
[])
ax
.
imshow
(
img
)
x
=
450
y
=
1750
for
k
,
n
in
enumerate
(
notes
):
i
=
k
/
10
j
=
k
%
10
plt
.
text
(
x
+
481
*
i
,
1750
+
j
*
100
,
str
(
n
),
color
=
"red"
)
plt
.
text
(
180
,
1000
,
login
+
" : "
+
str
(
note
),
color
=
"red"
,
fontsize
=
15
)
plt
.
draw
()
plt
.
savefig
(
sys
.
argv
[
3
],
dpi
=
dpi
)
pylene/include/mln/morpho/bounded_hqueue.hpp
deleted
100644 → 0
View file @
0fa63169
#pragma once
#include <mln/core/assert.hpp>
#include <array>
#include <memory>
#include <numeric>
#include <vector>
namespace
mln
{
template
<
typename
T
,
std
::
size_t
nLevel
,
typename
Allocator
=
std
::
allocator
<
T
>,
bool
queue
=
false
,
typename
Enable
=
void
>
struct
bounded_hqueue
{
bounded_hqueue
();
explicit
bounded_hqueue
(
const
size_t
*
histo
);
~
bounded_hqueue
();
void
init
(
const
size_t
*
histo
);
bool
empty
(
unsigned
l
)
const
;
void
push_at_level
(
const
T
&
x
,
unsigned
l
);
T
top_at_level
(
unsigned
l
)
const
;
T
pop_at_level
(
unsigned
l
);
private:
std
::
array
<
T
*
,
nLevel
>
m_head
;
std
::
array
<
T
*
,
nLevel
>
m_tail
;
Allocator
m_allocator
;
T
*
m_q
;
T
*
m_end
;
};
template
<
typename
T
,
std
::
size_t
nLevel
,
typename
Allocator
,
bool
queue
>
struct
bounded_hqueue
<
T
,
nLevel
,
Allocator
,
queue
,
std
::
enable_if_t
<
(
nLevel
>
16
)
>>
{
bounded_hqueue
();
explicit
bounded_hqueue
(
const
size_t
*
histo
);
~
bounded_hqueue
();
void
init
(
const
size_t
*
histo
);
bool
empty
(
unsigned
l
)
const
;
void
push_at_level
(
const
T
&
x
,
unsigned
l
);
T
top_at_level
(
unsigned
l
)
const
;
T
pop_at_level
(
unsigned
l
);
private:
std
::
vector
<
T
*>
m_head
;
std
::
vector
<
T
*>
m_tail
;
Allocator
m_allocator
;
T
*
m_q
;
T
*
m_end
;
};
/********************/
/** Implementation **/
/********************/
template
<
typename
T
,
std
::
size_t
nLevel
,
typename
Allocator
,
bool
queue
,
typename
Enable
>
inline
bounded_hqueue
<
T
,
nLevel
,
Allocator
,
queue
,
Enable
>::
bounded_hqueue
()
:
m_head
{{
NULL
,
}}
,
m_tail
{{
NULL
,
}}
,
m_q
(
NULL
)
,
m_end
(
NULL
)
{
}
template
<
typename
T
,
std
::
size_t
nLevel
,
typename
Allocator
,
bool
queue
,
typename
Enable
>
inline
bounded_hqueue
<
T
,
nLevel
,
Allocator
,
queue
,
Enable
>::
bounded_hqueue
(
const
size_t
*
histo
)
{
init
(
histo
);
}
template
<
typename
T
,
std
::
size_t
nLevel
,
typename
Allocator
,
bool
queue
,
typename
Enable
>
inline
bounded_hqueue
<
T
,
nLevel
,
Allocator
,
queue
,
Enable
>::~
bounded_hqueue
()
{
if
(
m_q
!=
NULL
)
{
for
(
unsigned
i
=
0
;
i
<
nLevel
;
++
i
)
for
(
T
*
ptr
=
m_head
[
i
];
ptr
!=
m_tail
[
i
];
++
ptr
)
m_allocator
.
destroy
(
ptr
);
m_allocator
.
deallocate
(
m_q
,
m_end
-
m_q
);
}
}
template
<
typename
T
,
std
::
size_t
nLevel
,
typename
Allocator
,
bool
queue
,
typename
Enable
>
inline
void
bounded_hqueue
<
T
,
nLevel
,
Allocator
,
queue
,
Enable
>::
init
(
const
size_t
*
histo
)
{
mln_precondition
(
m_q
==
NULL
);
unsigned
nelements
=
std
::
accumulate
(
histo
,
histo
+
nLevel
,
0u
);
m_q
=
m_allocator
.
allocate
(
nelements
);
m_end
=
m_q
+
nelements
;
unsigned
n
=
0
;
for
(
unsigned
i
=
0
;
i
<
nLevel
;
++
i
)
{
m_head
[
i
]
=
m_tail
[
i
]
=
m_q
+
n
;
n
+=
histo
[
i
];
}
}
template
<
typename
T
,
std
::
size_t
nLevel
,
typename
Allocator
,
bool
queue
,
typename
Enable
>
inline
bool
bounded_hqueue
<
T
,
nLevel
,
Allocator
,
queue
,
Enable
>::
empty
(
unsigned
level
)
const
{
mln_precondition
(
level
<
nLevel
);
return
m_head
[
level
]
==
m_tail
[
level
];
}
template
<
typename
T
,
std
::
size_t
nLevel
,
typename
Allocator
,
bool
queue
,
typename
Enable
>
inline
void
bounded_hqueue
<
T
,
nLevel
,
Allocator
,
queue
,
Enable
>::
push_at_level
(
const
T
&
x
,
unsigned
level
)
{
mln_precondition
(
level
<
nLevel
);
mln_precondition
(
m_tail
[
level
]
<
m_end
and
(
level
==
nLevel
-
1
or
m_tail
[
level
]
<
m_head
[
level
+
1
]));
m_allocator
.
construct
(
m_tail
[
level
]
++
,
x
);
}
template
<
typename
T
,
std
::
size_t
nLevel
,
typename
Allocator
,
bool
queue
,
typename
Enable
>
inline
T
bounded_hqueue
<
T
,
nLevel
,
Allocator
,
queue
,
Enable
>::
pop_at_level
(
unsigned
level
)
{
mln_precondition
(
level
<
nLevel
);
mln_precondition
(
!
empty
(
level
));
if
(
queue
)
{
T
x
=
std
::
move
(
*
(
m_head
[
level
]));
m_allocator
.
destroy
(
m_head
[
level
]
++
);
return
x
;
}
else
{
T
x
=
std
::
move
(
*
(
--
m_tail
[
level
]));
m_allocator
.
destroy
(
m_tail
[
level
]);
return
x
;
}
}
template
<
typename
T
,
std
::
size_t
nLevel
,
typename
Allocator
,
bool
queue
,
typename
Enable
>
inline
T
bounded_hqueue
<
T
,
nLevel
,
Allocator
,
queue
,
Enable
>::
top_at_level
(
unsigned
level
)
const
{
mln_precondition
(
level
<
nLevel
);
mln_precondition
(
!
empty
(
level
));
if
(
queue
)
{
T
x
=
*
(
m_head
[
level
]);
return
x
;
}
else
{
T
x
=
*
(
m_tail
[
level
]
-
1
);
return
x
;
}
}
/*********************************/
/* Implementation specialization */
/*********************************/
template
<
typename
T
,
std
::
size_t
nLevel
,
typename
Allocator
,
bool
queue
>
inline
bounded_hqueue
<
T
,
nLevel
,
Allocator
,
queue
,
std
::
enable_if_t
<
(
nLevel
>
16
)
>>::
bounded_hqueue
()
:
m_q
(
NULL
)
,
m_end
(
NULL
)
{
m_head
.
resize
(
nLevel
);
m_tail
.
resize
(
nLevel
);
}
template
<
typename
T
,
std
::
size_t
nLevel
,
typename
Allocator
,
bool
queue
>
inline
bounded_hqueue
<
T
,
nLevel
,
Allocator
,
queue
,
std
::
enable_if_t
<
(
nLevel
>
16
)
>>::
bounded_hqueue
(
const
size_t
*
histo
)
{
init
(
histo
);
}
template
<
typename
T
,
std
::
size_t
nLevel
,
typename
Allocator
,
bool
queue
>
inline
bounded_hqueue
<
T
,
nLevel
,
Allocator
,
queue
,
std
::
enable_if_t
<
(
nLevel
>
16
)
>>::~
bounded_hqueue
()
{
if
(
m_q
!=
NULL
)
{
for
(
std
::
size_t
i
=
0
;
i
<
nLevel
;
++
i
)
for
(
T
*
ptr
=
m_head
[
i
];
ptr
!=
m_tail
[
i
];
++
ptr
)
m_allocator
.
destroy
(
ptr
);
m_allocator
.
deallocate
(
m_q
,
m_end
-
m_q
);
}
}
template
<
typename
T
,
std
::
size_t
nLevel
,
typename
Allocator
,
bool
queue
>
inline
void
bounded_hqueue
<
T
,
nLevel
,
Allocator
,
queue
,
std
::
enable_if_t
<
(
nLevel
>
16
)
>>::
init
(
const
size_t
*
histo
)
{
mln_precondition
(
m_q
==
NULL
);
size_t
nelements
=
std
::
accumulate
(
histo
,
histo
+
nLevel
,
size_t
(
0
));
m_q
=
m_allocator
.
allocate
(
nelements
);
m_end
=
m_q
+
nelements
;
unsigned
n
=
0
;
for
(
std
::
size_t
i
=
0
;
i
<
nLevel
;
++
i
)
{
m_head
[
i
]
=
m_tail
[
i
]
=
m_q
+
n
;
n
+=
static_cast
<
unsigned
>
(
histo
[
i
]);
}
}
template
<
typename
T
,
std
::
size_t
nLevel
,
typename
Allocator
,
bool
queue
>
inline
bool
bounded_hqueue
<
T
,
nLevel
,
Allocator
,
queue
,
std
::
enable_if_t
<
(
nLevel
>
16
)
>>::
empty
(
unsigned
level
)
const
{
mln_precondition
(
level
<
nLevel
);
return
m_head
[
level
]
==
m_tail
[
level
];
}
template
<
typename
T
,
std
::
size_t
nLevel
,
typename
Allocator
,
bool
queue
>
inline
void
bounded_hqueue
<
T
,
nLevel
,
Allocator
,
queue
,
std
::
enable_if_t
<
(
nLevel
>
16
)
>>::
push_at_level
(
const
T
&
x
,
unsigned
level
)
{
mln_precondition
(
level
<
nLevel
);
mln_precondition
(
m_tail
[
level
]
<
m_end
and
(
level
==
nLevel
-
1
or
m_tail
[
level
]
<
m_head
[
level
+
1
]));
m_allocator
.
construct
(
m_tail
[
level
]
++
,
x
);
}
template
<
typename
T
,
std
::
size_t
nLevel
,
typename
Allocator
,
bool
queue
>
inline
T
bounded_hqueue
<
T
,
nLevel
,
Allocator
,
queue
,
std
::
enable_if_t
<
(
nLevel
>
16
)
>>::
pop_at_level
(
unsigned
level
)
{
mln_precondition
(
level
<
nLevel
);
mln_precondition
(
!
empty
(
level
));
if
(
queue
)
{
T
x
=
std
::
move
(
*
(
m_head
[
level
]));
m_allocator
.
destroy
(
m_head
[
level
]
++
);
return
x
;
}
else
{
T
x
=
std
::
move
(
*
(
--
m_tail
[
level
]));
m_allocator
.
destroy
(
m_tail
[
level
]);
return
x
;
}
}
template
<
typename
T
,
std
::
size_t
nLevel
,
typename
Allocator
,
bool
queue
>
inline
T
bounded_hqueue
<
T
,
nLevel
,
Allocator
,
queue
,
std
::
enable_if_t
<
(
nLevel
>
16
)
>>::
top_at_level
(
unsigned
level
)
const
{
mln_precondition
(
level
<
nLevel
);
mln_precondition
(
!
empty
(
level
));
if
(
queue
)
{
T
x
=
*
(
m_head
[
level
]);
return
x
;
}
else
{
T
x
=
*
(
m_tail
[
level
]
-
1
);
return
x
;
}
}
}
// namespace mln
pylene/include/mln/morpho/component_tree/io.hpp
deleted
100644 → 0
View file @
0fa63169
#pragma once
#include <mln/io/imread.hpp>
#include <mln/io/imsave.hpp>
#include <mln/morpho/component_tree/component_tree.hpp>
#include <iosfwd>
namespace
mln
{
namespace
morpho
{