Skip to content

Commit

Permalink
Fix class/module. Add spec
Browse files Browse the repository at this point in the history
  • Loading branch information
Antti committed Jan 10, 2024
1 parent 05d6d6f commit 594c014
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 5 deletions.
47 changes: 47 additions & 0 deletions lib/libfacedetection/facedetect.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
module Libfacedetection
module FaceDetection
require 'ruby-vips'
require 'ffi'

LIB_FACEDETECTION_MAX_SIZE = 400.0

extend self

# vips_img: Vips::Image
def detect_faces(vips_img)
scale =
if vips_img.width > vips_img.height
LIB_FACEDETECTION_MAX_SIZE / vips_img.width
else
LIB_FACEDETECTION_MAX_SIZE / vips_img.height
end
# convert RGB -> BGR
rgb_bands = vips_img.bandsplit
bgr = Vips::Image.bandjoin([rgb_bands[2], rgb_bands[1], rgb_bands[0]])
# resize to a smaller size - libfacedetection works with smaller images
# or perhaps a larger one, but results are not guaranteed to be better
resized = bgr.resize(scale)

mem = resized.write_to_memory
ptr = FFI::MemoryPointer.from_string(mem)
faces = Libfacedetection.detect_libfacedetection_image_data(ptr.address, resized.width, resized.height)
faces.map do |face|
scale_face(face, scale)
end
end

private

def scale_face(face, scale)
face[:x] = (face[:x] / scale).round
face[:y] = (face[:y] / scale).round
face[:width] = (face[:width] / scale).round
face[:height] = (face[:height] / scale).round
face[:landmarks] = face[:landmarks].map do |landmark|
[(landmark[0] / scale).round, (landmark[1] / scale).round]
end
face
end
end

end
2 changes: 2 additions & 0 deletions libfacedetection.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ Gem::Specification.new do |spec|
spec.extensions = ["Cargo.toml"]
spec.add_development_dependency "rake", "~> 13.0"
spec.add_development_dependency "gem-compiler"
spec.add_development_dependency "ruby-vips"
spec.add_development_dependency "ffi"
spec.required_rubygems_version = Gem::Requirement.new(">= 3.4.0") if spec.respond_to? :required_rubygems_version=
# spec.add_development_dependency "rake-compiler-dock", "~> 1.2.2"

Expand Down
10 changes: 5 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,16 +165,16 @@ fn features() -> Result<RArray> {

#[magnus::init]
fn init(ruby: &magnus::Ruby) -> Result<()> {
let class = ruby.define_class("Libfacedetection", ruby.class_object())?;
class.define_method("detect_opencv", magnus::function!(pub_detect_opencv, 1))?;
class.define_method(
let module = ruby.define_module("Libfacedetection")?;
module.define_module_function("detect_opencv", magnus::function!(pub_detect_opencv, 1))?;
module.define_module_function(
"detect_libfacedetection",
magnus::function!(pub_detect_libfacedetection, 1),
)?;
class.define_method(
module.define_module_function(
"detect_libfacedetection_image_data",
magnus::function!(pub_detect_libfacedetection_image_data, 3),
)?;
class.define_method("features", magnus::function!(features, 0))?;
module.define_module_function("features", magnus::function!(features, 0))?;
Ok(())
}
Binary file added tests/female.webp
Binary file not shown.
14 changes: 14 additions & 0 deletions tests/test_detection.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
gem 'libfacedetection'
require 'libfacedetection'
require 'libfacedetection/facedetect'

require 'minitest/autorun'

class FaceDetectionTest < Minitest::Test
def test_facedetection
result = Libfacedetection::FaceDetection.detect_faces(Vips::Image.new_from_file(File.expand_path("female.webp", __dir__)))
assert_instance_of(Array, result)
assert_equal(1, result.count)
assert(result[0][:confidence] > 90)
end
end

0 comments on commit 594c014

Please sign in to comment.