imogen 0.1.8 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|