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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fa9d6f61ab8d5aa8f99517c1d4d638cf3a5cb508179d05cf8262bd24f796df35
4
- data.tar.gz: 27dc10c53681b2fbd7ea25b258dd5d049c5bbf5b31dc4e01d16d25f829798300
3
+ metadata.gz: f78baebd0825df57e7ddeea7a7ca02c95a9c2c064c264532a911b12e72d289ad
4
+ data.tar.gz: c2d64e9187fa67bf65c6be9eb256cd430155609b4e5c8a0f2d5a48742fc87ceb
5
5
  SHA512:
6
- metadata.gz: f482b46a68ae037dd849cac3232ec7fe74a4902fde31a5c84c7ec323cbddb61a1138aa4192d58092b80acdbc0ae4475569e4d14bb4c17513d18cb8637cad5ae4
7
- data.tar.gz: e54a8310bb1af53d1cb6f2287ea6aa23fade2cf51980cc3096dec7fe91844b77c982d46373df67c0028a385175e1276cc7deed5356515e695339cff912cf8bf3
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
+ }
@@ -1,10 +1,11 @@
1
1
  #!ruby
2
- require 'opencv'
2
+ require 'imogencv'
3
3
  module Imogen::AutoCrop::Box
4
- include OpenCV
4
+ include ImogenCV
5
5
  class Best
6
6
  def initialize(grayscale)
7
- @corners = grayscale.good_features_to_track(0.3, 1.0, block_size: 3, max: 20)
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? OpenCV::CvMat
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 'opencv'
2
+ require 'imogencv'
3
3
  require 'free-image'
4
4
  require 'tempfile'
5
5
 
6
6
  module Imogen::AutoCrop
7
- class Edges
8
- include OpenCV
9
- def initialize(src)
10
- @xoffset = 0
11
- @yoffset = 0
12
- if src.is_a? FreeImage::Bitmap
13
- img = src
14
- @xoffset = img.width.to_f/6
15
- @yoffset = img.height.to_f/6
16
- if Imogen::AutoCrop::Box.squarish? img
17
- @xoffset = @xoffset/2
18
- @yoffset = @yoffset/2
19
- end
20
- @tempfile = Tempfile.new(['crop','.png'])
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
- img.copy(@xoffset,@yoffset,img.width-@xoffset,img.height-@yoffset) do |crop|
23
- crop.save(@tempfile.path, :png)
24
- crop.free
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
- else
27
- raise src.class.name
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
- # returns leftX, topY, rightX, bottomY
40
- def get(*args)
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
- return [c[0]-r, c[1]-r, c[0]+r, c[1] + r]
62
- end
63
- def unlink
64
- @tempfile.unlink
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
@@ -14,7 +14,6 @@ module Imogen
14
14
  thumb.free
15
15
  end
16
16
  end
17
- frame.unlink
18
17
  end
19
18
  end
20
- end
19
+ end
@@ -46,15 +46,11 @@ class Region < Transform
46
46
  else
47
47
  if edges == :featured
48
48
  frame = Imogen::AutoCrop::Edges.new(img)
49
- begin
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
@@ -104,4 +104,5 @@ module Imogen
104
104
  FreeImage::Bitmap.new(ptr, nil, &block)
105
105
  end
106
106
  end
107
- end
107
+ end
108
+ require 'imogencv'
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.8
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-16 00:00:00.000000000 Z
11
+ date: 2019-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: ruby-opencv
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