imogen 0.1.8 → 0.1.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/imogencv/extconf.rb +99 -0
- data/ext/imogencv/imogencv.cpp +87 -0
- data/lib/imogen/auto_crop/box.rb +5 -4
- data/lib/imogen/auto_crop/edges.rb +54 -54
- data/lib/imogen/auto_crop.rb +1 -2
- data/lib/imogen/iiif/region.rb +2 -6
- data/lib/imogen.rb +2 -1
- data/lib/imogencv.bundle +0 -0
- metadata +22 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f78baebd0825df57e7ddeea7a7ca02c95a9c2c064c264532a911b12e72d289ad
|
4
|
+
data.tar.gz: c2d64e9187fa67bf65c6be9eb256cd430155609b4e5c8a0f2d5a48742fc87ceb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 72f13fe92f9dc14fb61131218d84eb6516dab1a3737839e7377f717d0badee2ffe0bd8b57bb0c6fb6ba056bf2ad151c910296d09f1943e20bcaf96621c1db20d
|
7
|
+
data.tar.gz: 9eb6bd80a0dfa8d797a39267d805acde74e7ac33fe9395556db2d143396fe7aef0dd2603b9fd8df58b4b2d519adf24019b82113cf7506fca867a53eeb43404c4
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'mkmf-rice'
|
2
|
+
|
3
|
+
osx = RbConfig::CONFIG['target_os'] =~ /darwin/
|
4
|
+
|
5
|
+
if osx
|
6
|
+
$CFLAGS << " -x c++ -std=c++14"# damn the torpedoes!
|
7
|
+
else
|
8
|
+
$CFLAGS << " -x c++"
|
9
|
+
end
|
10
|
+
|
11
|
+
def real_inc_dir(src)
|
12
|
+
File.symlink?(src) ? File.realdirpath(src) : src
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_flags_if_header(header, header_dir, lib_dir)
|
16
|
+
a_file = File.join(header_dir, header)
|
17
|
+
exists = File.exist?(a_file)
|
18
|
+
puts "#{a_file} exists ... #{exists}"
|
19
|
+
if exists
|
20
|
+
inc_opt = "-I#{header_dir}".quote
|
21
|
+
lib_opt = "-L#{lib_dir}".quote
|
22
|
+
puts "adding compiler flags:\n#{inc_opt}\n#{lib_opt}"
|
23
|
+
$INCFLAGS << " " << inc_opt
|
24
|
+
$LIBPATH = $LIBPATH | [lib_dir]
|
25
|
+
end
|
26
|
+
exists
|
27
|
+
end
|
28
|
+
|
29
|
+
incdir_default = "/usr/local/include"
|
30
|
+
libdir_default = "/usr/local/lib"
|
31
|
+
|
32
|
+
have_library('stdc++')
|
33
|
+
# MakeMakefile::CONFTEST_C = "#{CONFTEST}.cc"
|
34
|
+
|
35
|
+
required_headers = {}
|
36
|
+
required_libs = {}
|
37
|
+
|
38
|
+
required_headers['opencv4'] = [ 'opencv2/features2d.hpp' ]
|
39
|
+
required_libs['opencv4'] = [
|
40
|
+
'opencv_core',
|
41
|
+
'opencv_imgcodecs',
|
42
|
+
'opencv_imgproc',
|
43
|
+
'opencv_features2d'
|
44
|
+
]
|
45
|
+
|
46
|
+
required_libs['zlib'] = ['z']
|
47
|
+
required_libs['libwebp'] = ['webp']
|
48
|
+
required_libs['libjpeg'] = ['jpeg']
|
49
|
+
required_libs['libtiff-4'] = ['tiff']
|
50
|
+
required_libs['libpng'] = ['png16']
|
51
|
+
required_libs['jasper'] = [] # just run pkg-config if you can
|
52
|
+
required_libs['OpenEXR'] = ['IlmImf']
|
53
|
+
|
54
|
+
all_deps = (required_libs.keys | required_headers.keys).sort.uniq
|
55
|
+
all_deps.each do |dep_key|
|
56
|
+
has_pkg_config = (pkg_config(dep_key) || []).detect { |c| c =~ /\-L\/\w+/ }
|
57
|
+
|
58
|
+
# expect to call with --with-opencv4-include=DIR and --with-opencv4-lib=DIR or --withopencv4-dir=DIR
|
59
|
+
incdir, libdir = dir_config(dep_key, incdir_default, libdir_default) unless has_pkg_config
|
60
|
+
|
61
|
+
unless !has_pkg_config && incdir && incdir != incdir_default
|
62
|
+
puts "using default #{dep_key} include path: #{incdir_default}"
|
63
|
+
end
|
64
|
+
|
65
|
+
unless !has_pkg_config && libdir && libdir != libdir_default
|
66
|
+
puts "using default #{dep_key} library path: #{libdir_default}"
|
67
|
+
end
|
68
|
+
|
69
|
+
include_paths = [incdir_default, "/usr/local"]
|
70
|
+
include_paths = ([incdir, File.join(incdir, dep_key)] | include_paths) if incdir
|
71
|
+
|
72
|
+
required_headers.fetch(dep_key, []).each do |hdr|
|
73
|
+
unless find_header(hdr, *include_paths.compact.uniq)
|
74
|
+
open(MakeMakefile::Logging.instance_variable_get(:@logfile), 'r') do |logblob|
|
75
|
+
logblob.each { |logline| puts logline.strip }
|
76
|
+
end
|
77
|
+
puts "Cannot find required header: #{hdr}"
|
78
|
+
puts "if this output is from rake compile, consider adding:"
|
79
|
+
puts "rake compile -- --with#{dep_key}-include=DIR"
|
80
|
+
exit 1
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
lib_paths = [libdir_default, "/usr/local"]
|
85
|
+
lib_paths.unshift(libdir) if libdir
|
86
|
+
|
87
|
+
required_libs.fetch(dep_key, []).each do |lib|
|
88
|
+
unless find_library(lib, nil, *lib_paths.compact.uniq)
|
89
|
+
puts "Cannot find required lib: #{lib}"
|
90
|
+
exit 1
|
91
|
+
end
|
92
|
+
end
|
93
|
+
append_cflags(lib_paths.compact.uniq.map {|x| "-L#{x}"}.join(' '))
|
94
|
+
end
|
95
|
+
|
96
|
+
append_cflags('-stdlib=libc++')
|
97
|
+
@libdir_basename ||= 'lib'
|
98
|
+
$LIBRUBYARG.prepend(' ') # there's some weird spacing issue in rice's lib linking routine
|
99
|
+
create_makefile('imogencv')
|
@@ -0,0 +1,87 @@
|
|
1
|
+
#include "rice/Class.hpp"
|
2
|
+
#include "rice/Constructor.hpp"
|
3
|
+
#include "rice/Enum.hpp"
|
4
|
+
#include "opencv2/features2d.hpp"
|
5
|
+
#include "opencv2/imgproc.hpp"
|
6
|
+
#include "opencv2/imgcodecs.hpp"
|
7
|
+
|
8
|
+
using namespace Rice;
|
9
|
+
|
10
|
+
Object process_kaze_features(Object r_image)
|
11
|
+
{
|
12
|
+
cv::Mat image = from_ruby<cv::Mat>(r_image);
|
13
|
+
std::vector<cv::KeyPoint> keyPoints;
|
14
|
+
cv::Ptr<cv::KAZE> alg = cv::KAZE::create();
|
15
|
+
cv::Mat features;
|
16
|
+
alg->detectAndCompute(image, cv::noArray(), keyPoints, features);
|
17
|
+
Array a;
|
18
|
+
for(cv::KeyPoint keyPoint : keyPoints)
|
19
|
+
{
|
20
|
+
a.push(to_ruby<cv::Point2f>(keyPoint.pt));
|
21
|
+
}
|
22
|
+
keyPoints.clear();
|
23
|
+
return a;
|
24
|
+
}
|
25
|
+
|
26
|
+
Object load_grayscale(Object filename)
|
27
|
+
{
|
28
|
+
Check_Type(filename, T_STRING);
|
29
|
+
cv::String const c_path = cv::String(String(filename).str());
|
30
|
+
cv::Mat image = imread(c_path, cv::IMREAD_GRAYSCALE);
|
31
|
+
return to_ruby<cv::Mat>(image);
|
32
|
+
}
|
33
|
+
|
34
|
+
Object point2f_x(Object self)
|
35
|
+
{
|
36
|
+
cv::Point2f point = from_ruby<cv::Point2f>(self);
|
37
|
+
return to_ruby<int>(point.x);
|
38
|
+
}
|
39
|
+
|
40
|
+
Object point2f_y(Object self)
|
41
|
+
{
|
42
|
+
cv::Point2f point = from_ruby<cv::Point2f>(self);
|
43
|
+
return to_ruby<int>(point.y);
|
44
|
+
}
|
45
|
+
|
46
|
+
Object mat_cols(Object self)
|
47
|
+
{
|
48
|
+
cv::Mat image = from_ruby<cv::Mat>(self);
|
49
|
+
return to_ruby<int>(image.cols);
|
50
|
+
}
|
51
|
+
|
52
|
+
Object mat_rows(Object self)
|
53
|
+
{
|
54
|
+
cv::Mat image = from_ruby<cv::Mat>(self);
|
55
|
+
return to_ruby<int>(image.rows);
|
56
|
+
}
|
57
|
+
|
58
|
+
Object mat_good_features_to_track(Object self, int maxCorners, double qualityLevel, double minDistance, int blockSize, bool useHarrisDetector, double k)
|
59
|
+
{
|
60
|
+
cv::Mat image = from_ruby<cv::Mat>(self);
|
61
|
+
cv::Mat mask;
|
62
|
+
std::vector<cv::Point2f> corners;
|
63
|
+
cv::goodFeaturesToTrack(image, corners, maxCorners, qualityLevel, minDistance, mask, blockSize, useHarrisDetector, k);
|
64
|
+
Array a;
|
65
|
+
for(cv::Point2f corner : corners)
|
66
|
+
{
|
67
|
+
a.push(to_ruby<cv::Point2f>(corner));
|
68
|
+
}
|
69
|
+
corners.clear();
|
70
|
+
return a;
|
71
|
+
}
|
72
|
+
|
73
|
+
extern "C"
|
74
|
+
void Init_imogencv()
|
75
|
+
{
|
76
|
+
Module rb_mOpenCV = define_module("ImogenCV");
|
77
|
+
Class rb_cKazeFeatures = rb_mOpenCV.define_class("KazeFeatures");
|
78
|
+
rb_cKazeFeatures.define_singleton_method("process", &process_kaze_features);
|
79
|
+
Data_Type<cv::Mat> rb_cMat = rb_mOpenCV.define_class<cv::Mat>("Mat")
|
80
|
+
.define_method(Identifier("cols"), &mat_cols)
|
81
|
+
.define_method(Identifier("rows"), &mat_rows)
|
82
|
+
.define_method("good_features_to_track", &mat_good_features_to_track)
|
83
|
+
.define_singleton_method("load_grayscale", &load_grayscale);
|
84
|
+
Data_Type<cv::Point2f> rb_cPoint2f = rb_mOpenCV.define_class<cv::Point2f>("Point2f")
|
85
|
+
.define_method(Identifier("x"), &point2f_x)
|
86
|
+
.define_method(Identifier("y"), &point2f_y);
|
87
|
+
}
|
data/lib/imogen/auto_crop/box.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
#!ruby
|
2
|
-
require '
|
2
|
+
require 'imogencv'
|
3
3
|
module Imogen::AutoCrop::Box
|
4
|
-
include
|
4
|
+
include ImogenCV
|
5
5
|
class Best
|
6
6
|
def initialize(grayscale)
|
7
|
-
|
7
|
+
# mat_good_features_to_track(std::int maxCorners, std::double qualityLevel, std:double minDistance, std::int blockSize, std::bool useHarrisDetector, std::double k)
|
8
|
+
@corners = grayscale.good_features_to_track(20, 0.3, 1.0, 3, false, 0.04)
|
8
9
|
if @corners.nil? or @corners.length == 0
|
9
10
|
@center = Center.new(grayscale)
|
10
11
|
else
|
@@ -77,7 +78,7 @@ module Imogen::AutoCrop::Box
|
|
77
78
|
dims = [img.width, img.height]
|
78
79
|
ratio = dims.min.to_f / dims.max
|
79
80
|
return ratio >= BoxInfo::SQUARISH
|
80
|
-
elsif img.is_a?
|
81
|
+
elsif img.is_a? ImogenCV::Mat
|
81
82
|
dims = [img.cols, img.rows]
|
82
83
|
ratio = dims.min.to_f / dims.max
|
83
84
|
return ratio >= BoxInfo::SQUARISH
|
@@ -1,67 +1,67 @@
|
|
1
1
|
#!ruby
|
2
|
-
require '
|
2
|
+
require 'imogencv'
|
3
3
|
require 'free-image'
|
4
4
|
require 'tempfile'
|
5
5
|
|
6
6
|
module Imogen::AutoCrop
|
7
|
-
class Edges
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
7
|
+
class Edges
|
8
|
+
include ImogenCV
|
9
|
+
def initialize(src)
|
10
|
+
@xoffset = 0
|
11
|
+
@yoffset = 0
|
12
|
+
tempfile = nil
|
13
|
+
if src.is_a? FreeImage::Bitmap
|
14
|
+
img = src
|
15
|
+
@xoffset = img.width.to_f/6
|
16
|
+
@yoffset = img.height.to_f/6
|
17
|
+
if Imogen::AutoCrop::Box.squarish? img
|
18
|
+
@xoffset = @xoffset/2
|
19
|
+
@yoffset = @yoffset/2
|
20
|
+
end
|
21
|
+
tempfile = Tempfile.new(['crop','.png'])
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
23
|
+
img.copy(@xoffset,@yoffset,img.width-@xoffset,img.height-@yoffset) do |crop|
|
24
|
+
crop.save(tempfile.path, :png)
|
25
|
+
crop.free
|
26
|
+
end
|
27
|
+
else
|
28
|
+
raise src.class.name
|
25
29
|
end
|
26
|
-
|
27
|
-
|
30
|
+
# use bigger features on bigger images
|
31
|
+
@grayscale = ImogenCV::Mat.load_grayscale(tempfile.path)
|
32
|
+
@xrange = (0..@grayscale.cols)
|
33
|
+
@yrange = (0..@grayscale.rows)
|
34
|
+
ensure
|
35
|
+
tempfile.unlink if tempfile
|
28
36
|
end
|
29
|
-
# use bigger features on bigger images
|
30
|
-
@grayscale = CvMat.load(@tempfile.path, CV_LOAD_IMAGE_GRAYSCALE)
|
31
|
-
@xrange = (0..@grayscale.cols)
|
32
|
-
@yrange = (0..@grayscale.rows)
|
33
|
-
end
|
34
|
-
|
35
|
-
def bound_min(center)
|
36
|
-
[center.x - @xrange.min, @xrange.max - center.x, center.y - @yrange.min, @yrange.max - center.y].min
|
37
|
-
end
|
38
37
|
|
39
|
-
|
40
|
-
|
41
|
-
c = Imogen::AutoCrop::Box.info(@grayscale)
|
42
|
-
r = c.radius.floor
|
43
|
-
# adjust the box
|
44
|
-
coords = [c.x, c.y]
|
45
|
-
min_rad = args.max/2
|
46
|
-
unless r >= min_rad && r <= bound_min(c)
|
47
|
-
# first adjust to the lesser of max (half short dimension) and min (half requested length) radius
|
48
|
-
# this might require upscaling in rare situations to preserve bound safety
|
49
|
-
r = min_rad if r < min_rad
|
50
|
-
max_rad = [@xrange.max - @xrange.min, @yrange.max - @yrange.min].min / 2
|
51
|
-
r = max_rad if r > max_rad
|
52
|
-
# now move the center point minimally to accomodate the necessary radius
|
53
|
-
coords[0] = @xrange.max - r if (coords[0] + r) > @xrange.max
|
54
|
-
coords[0] = @xrange.min + r if (coords[0] - r) < @xrange.min
|
55
|
-
coords[1] = @yrange.max - r if (coords[1] + r) > @yrange.max
|
56
|
-
coords[1] = @yrange.min + r if (coords[1] - r) < @yrange.min
|
38
|
+
def bound_min(center)
|
39
|
+
[center.x - @xrange.min, @xrange.max - center.x, center.y - @yrange.min, @yrange.max - center.y].min
|
57
40
|
end
|
58
|
-
coords = [coords[0] + @xoffset, coords[1] + @yoffset].collect {|i| i.floor}
|
59
|
-
c = coords
|
60
41
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
42
|
+
# returns leftX, topY, rightX, bottomY
|
43
|
+
def get(*args)
|
44
|
+
c = Imogen::AutoCrop::Box.info(@grayscale)
|
45
|
+
r = c.radius.floor
|
46
|
+
# adjust the box
|
47
|
+
coords = [c.x, c.y]
|
48
|
+
min_rad = args.max/2
|
49
|
+
unless r >= min_rad && r <= bound_min(c)
|
50
|
+
# first adjust to the lesser of max (half short dimension) and min (half requested length) radius
|
51
|
+
# this might require upscaling in rare situations to preserve bound safety
|
52
|
+
r = min_rad if r < min_rad
|
53
|
+
max_rad = [@xrange.max - @xrange.min, @yrange.max - @yrange.min].min / 2
|
54
|
+
r = max_rad if r > max_rad
|
55
|
+
# now move the center point minimally to accomodate the necessary radius
|
56
|
+
coords[0] = @xrange.max - r if (coords[0] + r) > @xrange.max
|
57
|
+
coords[0] = @xrange.min + r if (coords[0] - r) < @xrange.min
|
58
|
+
coords[1] = @yrange.max - r if (coords[1] + r) > @yrange.max
|
59
|
+
coords[1] = @yrange.min + r if (coords[1] - r) < @yrange.min
|
60
|
+
end
|
61
|
+
coords = [coords[0] + @xoffset, coords[1] + @yoffset].collect {|i| i.floor}
|
62
|
+
c = coords
|
63
|
+
|
64
|
+
return [c[0]-r, c[1]-r, c[0]+r, c[1] + r]
|
65
|
+
end
|
65
66
|
end
|
66
67
|
end
|
67
|
-
end
|
data/lib/imogen/auto_crop.rb
CHANGED
data/lib/imogen/iiif/region.rb
CHANGED
@@ -46,15 +46,11 @@ class Region < Transform
|
|
46
46
|
else
|
47
47
|
if edges == :featured
|
48
48
|
frame = Imogen::AutoCrop::Edges.new(img)
|
49
|
-
|
50
|
-
edges = frame.get([img.width, img.height,768].min)
|
51
|
-
ensure
|
52
|
-
frame.unlink
|
53
|
-
end
|
49
|
+
edges = frame.get([img.width, img.height,768].min)
|
54
50
|
end
|
55
51
|
img.copy(*edges) {|crop| yield crop}
|
56
52
|
end
|
57
53
|
end
|
58
54
|
end
|
59
55
|
end
|
60
|
-
end
|
56
|
+
end
|
data/lib/imogen.rb
CHANGED
data/lib/imogencv.bundle
ADDED
Binary file
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: imogen
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Armintor
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-10-
|
11
|
+
date: 2019-10-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: rice
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
@@ -38,12 +38,29 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake-compiler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
description:
|
42
56
|
email: armintor@gmail.com
|
43
57
|
executables: []
|
44
|
-
extensions:
|
58
|
+
extensions:
|
59
|
+
- ext/imogencv/extconf.rb
|
45
60
|
extra_rdoc_files: []
|
46
61
|
files:
|
62
|
+
- ext/imogencv/extconf.rb
|
63
|
+
- ext/imogencv/imogencv.cpp
|
47
64
|
- lib/imogen.rb
|
48
65
|
- lib/imogen/auto_crop.rb
|
49
66
|
- lib/imogen/auto_crop/box.rb
|
@@ -55,6 +72,7 @@ files:
|
|
55
72
|
- lib/imogen/iiif/size.rb
|
56
73
|
- lib/imogen/iiif/tiles.rb
|
57
74
|
- lib/imogen/zoomable.rb
|
75
|
+
- lib/imogencv.bundle
|
58
76
|
- spec/spec_helper.rb
|
59
77
|
- spec/unit/imogen_iiif_quality_spec.rb
|
60
78
|
- spec/unit/imogen_iiif_region_spec.rb
|