From 53aed44ece10298140d23be59050287becb82da1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ianar=C3=A9=20S=C3=A9vi?= Date: Thu, 18 Sep 2025 10:56:56 +0200 Subject: [PATCH] :bug: fix polygon handling --- lib/mindee/geometry/polygon.rb | 9 ++++++++ lib/mindee/geometry/utils.rb | 15 +------------ lib/mindee/parsing/common/ocr/ocr.rb | 2 +- lib/mindee/parsing/standard/abstract_field.rb | 2 +- lib/mindee/parsing/standard/position_field.rb | 2 +- lib/mindee/parsing/v2/field/field_location.rb | 7 ++---- sig/mindee/geometry/polygon.rbs | 1 + .../parsing/v2/field/field_location.rbs | 4 ++-- spec/parsing/v2/inference_spec.rb | 22 +++++++++++-------- 9 files changed, 31 insertions(+), 33 deletions(-) diff --git a/lib/mindee/geometry/polygon.rb b/lib/mindee/geometry/polygon.rb index e02078de8..28c7f4469 100644 --- a/lib/mindee/geometry/polygon.rb +++ b/lib/mindee/geometry/polygon.rb @@ -5,6 +5,15 @@ module Mindee module Geometry # Contains any number of vertex coordinates (Points). class Polygon < Array + # @param server_response [Hash] Raw server response hash. + def initialize(server_response) + points = [] + server_response.map do |point| + points << Point.new(point[0], point[1]) + end + super(points) + end + # Get the central point (centroid) of the polygon. # @return [Mindee::Geometry::Point] def centroid diff --git a/lib/mindee/geometry/utils.rb b/lib/mindee/geometry/utils.rb index b5612ca73..420589c23 100644 --- a/lib/mindee/geometry/utils.rb +++ b/lib/mindee/geometry/utils.rb @@ -17,19 +17,6 @@ def self.quadrilateral_from_prediction(prediction) ) end - # Transform a prediction into a Polygon. - # @param prediction [Hash] - # @return [Mindee::Geometry::Polygon] - def self.polygon_from_prediction(prediction) - polygon = Polygon.new - return polygon if prediction.nil? - - prediction.each do |point| - polygon << Point.new(point[0], point[1]) - end - polygon - end - # Gets the points of a bounding box for a given set of points # @param vertices [Array] # @return [Array] @@ -39,7 +26,7 @@ def self.get_bbox(vertices) [x_coords.min, y_coords.min, x_coords.max, y_coords.max] end - # Creates the bounding bounding box for a given set of points + # Creates the bounding box for a given set of points # @param vertices [Array] # @return [Mindee::Geometry::Quadrilateral] def self.get_bounding_box(vertices) diff --git a/lib/mindee/parsing/common/ocr/ocr.rb b/lib/mindee/parsing/common/ocr/ocr.rb index 95c3cfb96..b7c898908 100644 --- a/lib/mindee/parsing/common/ocr/ocr.rb +++ b/lib/mindee/parsing/common/ocr/ocr.rb @@ -23,7 +23,7 @@ class OCRWord def initialize(prediction) @text = prediction['text'] @confidence = prediction['confidence'] - @polygon = Geometry.polygon_from_prediction(prediction['polygon']) + @polygon = Mindee::Geometry::Polygon.new(prediction['polygon']) @bounding_box = Geometry.get_bounding_box(@polygon) unless @polygon.nil? || @polygon.empty? end diff --git a/lib/mindee/parsing/standard/abstract_field.rb b/lib/mindee/parsing/standard/abstract_field.rb index 501825f40..65f2c62be 100644 --- a/lib/mindee/parsing/standard/abstract_field.rb +++ b/lib/mindee/parsing/standard/abstract_field.rb @@ -21,7 +21,7 @@ class AbstractField # @param page_id [Integer, nil] def initialize(prediction, page_id) @confidence = prediction['confidence'] if prediction.key?('confidence') - @polygon = Geometry.polygon_from_prediction(prediction['polygon']) if prediction.key?('polygon') + @polygon = Mindee::Geometry::Polygon.new(prediction['polygon']) if prediction.key?('polygon') @bounding_box = Geometry.get_bounding_box(@polygon) unless @polygon.nil? || @polygon.empty? @page_id = page_id || prediction['page_id'] end diff --git a/lib/mindee/parsing/standard/position_field.rb b/lib/mindee/parsing/standard/position_field.rb index 84d6c7a53..c0e2c3b63 100644 --- a/lib/mindee/parsing/standard/position_field.rb +++ b/lib/mindee/parsing/standard/position_field.rb @@ -20,7 +20,7 @@ class PositionField # @param page_id [Integer, nil] def initialize(prediction, page_id) unless prediction['polygon'].nil? || prediction['polygon'].empty? - @polygon = Geometry.polygon_from_prediction(prediction['polygon']) + @polygon = Mindee::Geometry::Polygon.new(prediction['polygon']) end @quadrangle = to_quadrilateral(prediction, 'quadrangle') @rectangle = to_quadrilateral(prediction, 'rectangle') diff --git a/lib/mindee/parsing/v2/field/field_location.rb b/lib/mindee/parsing/v2/field/field_location.rb index 424473c9c..e6902988b 100644 --- a/lib/mindee/parsing/v2/field/field_location.rb +++ b/lib/mindee/parsing/v2/field/field_location.rb @@ -16,11 +16,8 @@ class FieldLocation # @param server_response [Hash] Raw server response hash. def initialize(server_response) - polygon_data = server_response['polygon'] || server_response[:polygon] - @polygon = polygon_data ? Mindee::Geometry::Polygon.new(polygon_data) : nil - - page_id = server_response['page'] || server_response[:page] - @page = page_id.is_a?(Float) || page_id.is_a?(Integer) ? page_id.to_i : nil + @polygon = Mindee::Geometry::Polygon.new(server_response['polygon']) + @page = server_response['page'] end # String representation of the polygon (empty string when none). diff --git a/sig/mindee/geometry/polygon.rbs b/sig/mindee/geometry/polygon.rbs index 559d912d6..19f8b7c51 100644 --- a/sig/mindee/geometry/polygon.rbs +++ b/sig/mindee/geometry/polygon.rbs @@ -2,6 +2,7 @@ module Mindee module Geometry class Polygon < Array[Point] + def initialize: (Array[::Mindee::Geometry::Point | Array[Float]]) -> void def centroid: -> Point def point_in_y?: (Point) -> bool end diff --git a/sig/mindee/parsing/v2/field/field_location.rbs b/sig/mindee/parsing/v2/field/field_location.rbs index d72e31cc6..0c400ee08 100644 --- a/sig/mindee/parsing/v2/field/field_location.rbs +++ b/sig/mindee/parsing/v2/field/field_location.rbs @@ -4,8 +4,8 @@ module Mindee module V2 module Field class FieldLocation - attr_reader page: Integer? - attr_reader polygon: Geometry::Polygon? + attr_reader page: Integer + attr_reader polygon: Geometry::Polygon def initialize: (Hash[String | Symbol, untyped]) -> void def to_s: -> String diff --git a/spec/parsing/v2/inference_spec.rb b/spec/parsing/v2/inference_spec.rb index bc03d259b..9738ce1c9 100644 --- a/spec/parsing/v2/inference_spec.rb +++ b/spec/parsing/v2/inference_spec.rb @@ -308,19 +308,23 @@ def load_standard_fields expect(date_field.locations[0].page).to eq(0) polygon = date_field.locations[0].polygon - expect(polygon[0].length).to eq(2) + expect(polygon[0]).to be_a(Mindee::Geometry::Point) - expect(polygon[0][0]).to be_within(1e-12).of(0.948979073166918) - expect(polygon[0][1]).to be_within(1e-12).of(0.23097924535067715) + expect(polygon[0].x).to eq(0.948979073166918) + expect(polygon[0].y).to eq(0.23097924535067715) - expect(polygon[1][0]).to be_within(1e-12).of(0.85422) - expect(polygon[1][1]).to be_within(1e-12).of(0.230072) + expect(polygon[1][0]).to eq(0.85422) + expect(polygon[1][1]).to eq(0.230072) - expect(polygon[2][0]).to be_within(1e-12).of(0.8540899268330819) - expect(polygon[2][1]).to be_within(1e-12).of(0.24365775464932288) + expect(polygon[2][0]).to eq(0.8540899268330819) + expect(polygon[2][1]).to eq(0.24365775464932288) - expect(polygon[3][0]).to be_within(1e-12).of(0.948849) - expect(polygon[3][1]).to be_within(1e-12).of(0.244565) + expect(polygon[3][0]).to eq(0.948849) + expect(polygon[3][1]).to eq(0.244565) + + centroid = polygon.centroid + expect(centroid.x).to eq(0.9015345) + expect(centroid.y).to eq(0.23731850000000002) confidence = date_field.confidence expect(confidence).to be_a(field_confidence)