From: Pierre C. <Ba...@us...> - 2012-05-14 21:47:29
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "krobot". The branch, master has been updated via 08c2505def22aa273c38c7174e02e3b8f2255df8 (commit) via a251326d374e2c0795e63a3202674f2726dd8390 (commit) from 35f2720c1b040772eeefd7d06efd6ad4f3be3220 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 08c2505def22aa273c38c7174e02e3b8f2255df8 Author: chicco <cha...@cr...> Date: Mon May 14 23:47:06 2012 +0200 update vision, add detection tests commit a251326d374e2c0795e63a3202674f2726dd8390 Author: chicco <cha...@cr...> Date: Mon May 14 23:45:22 2012 +0200 update viewer for the new table, add message for coins position, add tool to detect coins ----------------------------------------------------------------------- Changes: diff --git a/info/control2011/_oasis b/info/control2011/_oasis index 587f26e..3227ab2 100644 --- a/info/control2011/_oasis +++ b/info/control2011/_oasis @@ -240,6 +240,13 @@ Executable "krobot-ax12-clean" CompiledObject: best MainIs: krobot_ax12_clean.ml +Executable "krobot-see-coin" + Path: src/tools + Install: true + CompiledObject: best + MainIs: krobot_see_coin.ml + BuildDepends: krobot, cv, lwt.syntax + # +-------------------------------------------------------------------+ # | Examples | # +-------------------------------------------------------------------+ diff --git a/info/control2011/_tags b/info/control2011/_tags index 8e8eb2b..c2c77dd 100644 --- a/info/control2011/_tags +++ b/info/control2011/_tags @@ -2,7 +2,7 @@ <src/interfaces/*.ml>: -syntax_camlp4o # OASIS_START -# DO NOT EDIT (digest: c7b4424d285a5d14617154af42598aa7) +# DO NOT EDIT (digest: 8b68a015ff8be0607836f173f33170fd) # Ignore VCS directories, you can use the same kind of rule outside # OASIS_START/STOP if you want to exclude directories that contains # useless stuff for the build process @@ -114,6 +114,13 @@ # Executable krobot-hub <src/tools/krobot_hub.{native,byte}>: pkg_lwt.unix <src/tools/krobot_hub.{native,byte}>: pkg_lwt.syntax +# Executable krobot-see-coin +<src/tools/krobot_see_coin.{native,byte}>: use_krobot +<src/tools/krobot_see_coin.{native,byte}>: pkg_lwt.unix +<src/tools/krobot_see_coin.{native,byte}>: pkg_lwt.syntax +<src/tools/krobot_see_coin.{native,byte}>: pkg_lwt.react +<src/tools/krobot_see_coin.{native,byte}>: pkg_cv +<src/tools/*.ml{,i}>: pkg_cv # Executable krobot-sharps <src/tools/krobot_sharps.{native,byte}>: use_krobot <src/tools/krobot_sharps.{native,byte}>: pkg_lwt.unix diff --git a/info/control2011/setup.ml b/info/control2011/setup.ml index a2b32ae..e0ea140 100644 --- a/info/control2011/setup.ml +++ b/info/control2011/setup.ml @@ -1,7 +1,7 @@ (* setup.ml generated for the first time by OASIS v0.2.0~alpha1 *) (* OASIS_START *) -(* DO NOT EDIT (digest: 8dd92996e901c6afd5668c8d5fed679a) *) +(* DO NOT EDIT (digest: 6276a9db280e9f6fd9a16f0e5e4359c8) *) (* Regenerated by OASIS v0.3.0~rc3 Visit http://oasis.forge.ocamlcore.org for more information and @@ -5777,6 +5777,35 @@ let setup_t = {exec_custom = false; exec_main_is = "krobot_hub.ml"; }); Executable ({ + cs_name = "krobot-see-coin"; + cs_data = PropList.Data.create (); + cs_plugin_data = []; + }, + { + bs_build = [(OASISExpr.EBool true, true)]; + bs_install = [(OASISExpr.EBool true, true)]; + bs_path = "src/tools"; + bs_compiled_object = Best; + bs_build_depends = + [ + InternalLibrary "krobot"; + FindlibPackage ("cv", None); + FindlibPackage ("lwt.syntax", None) + ]; + bs_build_tools = [ExternalTool "ocamlbuild"]; + bs_c_sources = []; + bs_data_files = []; + bs_ccopt = [(OASISExpr.EBool true, [])]; + bs_cclib = [(OASISExpr.EBool true, [])]; + bs_dlllib = [(OASISExpr.EBool true, [])]; + bs_dllpath = [(OASISExpr.EBool true, [])]; + bs_byteopt = [(OASISExpr.EBool true, [])]; + bs_nativeopt = [(OASISExpr.EBool true, [])]; + }, + {exec_custom = false; exec_main_is = "krobot_see_coin.ml"; + }); + Executable + ({ cs_name = "krobot-sharps"; cs_data = PropList.Data.create (); cs_plugin_data = []; @@ -6191,13 +6220,13 @@ let setup_t = }; oasis_fn = Some "_oasis"; oasis_version = "0.3.0~rc3"; - oasis_digest = Some "[\188\237\193\021xw\196\204\204<Y\157o\194F"; + oasis_digest = Some "\189Q=v\151\180\162\208\188\238+\208>;\014V"; oasis_exec = None; oasis_setup_args = []; };; let setup () = BaseSetup.setup setup_t;; -# 6202 "setup.ml" +# 6231 "setup.ml" (* OASIS_STOP *) let () = setup ();; diff --git a/info/control2011/src/can/libkrobot-can_stubs.clib b/info/control2011/src/can/libkrobot-can_stubs.clib new file mode 100644 index 0000000..0c062e7 --- /dev/null +++ b/info/control2011/src/can/libkrobot-can_stubs.clib @@ -0,0 +1,4 @@ +# OASIS_START +# DO NOT EDIT (digest: c331c7eb709b41509f57de577257bebd) +can_stubs.o +# OASIS_STOP diff --git a/info/control2011/src/lib/krobot_bus.ml b/info/control2011/src/lib/krobot_bus.ml index bb2d08a..0776640 100644 --- a/info/control2011/src/lib/krobot_bus.ml +++ b/info/control2011/src/lib/krobot_bus.ml @@ -37,6 +37,7 @@ type message = | Strategy_stop | Strategy_set of Krobot_action.t list | Strategy_path of Bezier.curve list option + | Coins of vertice list type t = { oc : Lwt_io.output_channel; @@ -111,6 +112,10 @@ let string_of_message = function sprintf "Strategy_path(Some [%s])" (String.concat "; " (List.map Bezier.string_of_curve curves)) + | Coins coins -> + sprintf + "Coins [%s]" + (String.concat "; " (List.map string_of_vertice coins)) (* +-----------------------------------------------------------------+ | Sending/receiving messages | diff --git a/info/control2011/src/lib/krobot_bus.mli b/info/control2011/src/lib/krobot_bus.mli index bef8110..59bd8e1 100644 --- a/info/control2011/src/lib/krobot_bus.mli +++ b/info/control2011/src/lib/krobot_bus.mli @@ -69,6 +69,9 @@ type message = (** Message emitted when the robot starts or stops a trajectory. *) + (** Vision *) + | Coins of vertice list + val string_of_message : message -> string (** Returns a string representation of the given message. *) diff --git a/info/control2011/src/lib/krobot_config.ml b/info/control2011/src/lib/krobot_config.ml index 749977a..4c5ef37 100644 --- a/info/control2011/src/lib/krobot_config.ml +++ b/info/control2011/src/lib/krobot_config.ml @@ -9,7 +9,7 @@ let sqr x = x *. x -let world_height = 2.1 +let world_height = 2. let world_width = 3. let robot_size = 0.26 let wheels_diameter = 0.098 @@ -20,3 +20,5 @@ let object_radius = 0.1 let border_safety_distance = sqrt (sqr robot_size /. 2.) +. 0.05 let object_safety_distance = object_radius +. robot_size /. 2. let beacon_safety_distance = 0.7 + +let coin_radius = 0.12 diff --git a/info/control2011/src/lib/krobot_config.mli b/info/control2011/src/lib/krobot_config.mli index deba593..def3497 100644 --- a/info/control2011/src/lib/krobot_config.mli +++ b/info/control2011/src/lib/krobot_config.mli @@ -43,3 +43,6 @@ val object_safety_distance : float val beacon_safety_distance : float (** Minimum distance between the center of the robot and the beacon. *) + +val coin_radius : float + (** Radius of coins. *) diff --git a/info/control2011/src/lib/krobot_geom.ml b/info/control2011/src/lib/krobot_geom.ml index a7a1dea..2f87a84 100644 --- a/info/control2011/src/lib/krobot_geom.ml +++ b/info/control2011/src/lib/krobot_geom.ml @@ -91,6 +91,16 @@ let tangents a b c = let v1 = ba -| bc and v2 = bc -| ba in (v1 /| norm v1, v2 /| norm v2) +let rot_mat theta = + [| [| cos theta; -. (sin theta); 0.; |]; + [| sin theta; cos theta; 0. |]; + [| 0.; 0.; 1. |]; |] + +let mult m v = + Array.init (Array.length m) + (fun k -> Array.fold_left (+.) 0. + (Array.mapi (fun i n -> v.(i) *. n) m.(k))) + (* +-----------------------------------------------------------------+ | Cubic bezier curves | +-----------------------------------------------------------------+ *) diff --git a/info/control2011/src/lib/krobot_geom.mli b/info/control2011/src/lib/krobot_geom.mli index a2fbbd5..71ec7e9 100644 --- a/info/control2011/src/lib/krobot_geom.mli +++ b/info/control2011/src/lib/krobot_geom.mli @@ -46,6 +46,11 @@ val tangents : vertice -> vertice -> vertice -> vector * vector (** [tangents a b c] returns the two unitary vectors tangent to the triangle abc in b. *) +val rot_mat : float -> float array array + +val mult : float array array -> float array -> float array +(** [mult m v] matrix multiplication *) + (** {6 Cubic Bezier curves} *) module Bezier : sig diff --git a/info/control2011/src/lib/libkrobot_stubs.clib b/info/control2011/src/lib/libkrobot_stubs.clib new file mode 100644 index 0000000..2fd3bec --- /dev/null +++ b/info/control2011/src/lib/libkrobot_stubs.clib @@ -0,0 +1,4 @@ +# OASIS_START +# DO NOT EDIT (digest: a4550602349a377958d2b340260718d0) +krobot_message_stubs.o +# OASIS_STOP diff --git a/info/control2011/src/tools/krobot_read_dump.ml b/info/control2011/src/tools/krobot_read_dump.ml new file mode 100644 index 0000000..e69de29 diff --git a/info/control2011/src/tools/krobot_see_coin.ml b/info/control2011/src/tools/krobot_see_coin.ml new file mode 100644 index 0000000..cf859de --- /dev/null +++ b/info/control2011/src/tools/krobot_see_coin.ml @@ -0,0 +1,230 @@ +open Lwt +open Lwt_react +open Krobot_bus +open Krobot_geom +open Krobot_config +open Krobot_message +open CvCore +open CvHighGui + +let section = Lwt_log.Section.make "krobot(see_coin)" + +(* +-----------------------------------------------------------------+ + | vision initialisation | + +-----------------------------------------------------------------+ *) + +let calibration_file = ref None +let homography_file = ref None +let color_filter_file = ref None + +let file_string file = + let file = open_in file in + let l = in_channel_length file in + let s = String.create l in + ignore(Pervasives.input file s 0 l); + s + +type color_filter = + { s_bounds : int * int; + v_bounds : int *int; } + +let load_color_filter () = match !color_filter_file with + | None -> + lwt () = Lwt_log.warning "No color config provided" in + return { s_bounds = 0, 100; + v_bounds = 150, 255; } + | Some file -> + try_lwt + let f = file_string file in + Scanf.sscanf f "s %i %i\nv %i %i\n" + (fun s1 s2 v1 v2 -> + return { v_bounds = v1, v2; s_bounds = s1, s2 }) + with + | exn -> + lwt () = Lwt_log.error ~exn "can't load color file" in + raise_lwt exn + +let load_calibration () = match !calibration_file with + | None -> + lwt () = Lwt_log.warning "No calibration config provided" in + return ([|[|1.;0.;1.;|]; + [|0.;1.;1.;|]; + [|0.;0.;1.;|]|], + [|0.;0.;0.;0.;0.|]) + | Some file -> + try_lwt + return (load_calibration_file file) + with + | exn -> + lwt () = Lwt_log.error ~exn "can't load calibration file" in + raise_lwt exn + +let load_homography () = match !homography_file with + | None -> + lwt () = Lwt_log.warning "No homography config provided" in + return [|[|1.;0.;0.;|]; + [|0.;1.;0.;|]; + [|0.;0.;1.;|]|] + | Some file -> + try_lwt + return (load_homography_file file) + with + | exn -> + lwt () = Lwt_log.error ~exn "can't load homography file" in + raise_lwt exn + +let rec get_cam i m = + if i <= m + then + try + Some (capture_from_cam i) + with + | _ -> get_cam (i+1) m + else None + +type vision = { + capture : cvCapture; + size : cvSize; + color_filter : color_filter; + remap : remap; + homography : float array array; + inv_homography : float array array; +} + +let init_capture () = + match get_cam 0 10 with + | None -> + lwt () = Lwt_log.error "Can't acquire webcam" in + raise_lwt (Failure "Can't acquire webcam") + | Some capture -> + set_capture_property capture CV_CAP_PROP_FRAME_HEIGHT 480.; + set_capture_property capture CV_CAP_PROP_FRAME_WIDTH 640.; + let i = query_frame capture in + let size = image_size i in + lwt color_filter = load_color_filter () in + lwt calibration = load_calibration () in + let remap_info = init_undistort_map size calibration in + lwt homography = load_homography () in + let det, inv_homography = invert homography in + return { capture; + size; + color_filter; + remap = remap_info; + homography; + inv_homography; } + +(* +-----------------------------------------------------------------+ + | Main vision code | + +-----------------------------------------------------------------+ *) + +let rec filter_map f l = + match l with + | [] -> [] + | t::q -> + match f t with + | None -> filter_map f q + | Some t -> t::(filter_map f q) + +let detect_ellipse vision = + let src = query_frame vision.capture in + let src = remap vision.remap src in + let hsv = convert_color src bgr2hsv in + let h,s,v = split hsv in + let vmin, vmax = vision.color_filter.v_bounds in + let v = between v vmin vmax in + let smin, smax = vision.color_filter.s_bounds in + let s = between s smin smax in + + let filtered = copy s (Some v) in + let filtered = erode filtered (5,5) in + let filtered = dilate filtered (5,5) in + let contours = contours (find_contours filtered) in + let ellipses = filter_map (fun (Contour (c,l)) -> + fit_ellipse c) contours in + (* TODO: filter good ellipses *) + ellipses + +let loop bus vision = + let rec aux () = + let time = Unix.gettimeofday () in + let ellipses = detect_ellipse vision in + let time2 = Unix.gettimeofday () in + lwt () = Lwt_log.info_f "vision compute time: %f" (time2 -. time) in + let norm v = + match v with + | [|a;b;c|] -> { x = a/.c; y = b/.c } + | _ -> assert false in + let vertices = List.map + (fun e -> let x,y = e.ellipse_center in + norm (mult vision.inv_homography [|x;y;1.|]) ) + ellipses in + let msg = Coins vertices in + lwt () = Krobot_bus.send bus (time, msg) in + lwt () = Lwt_unix.sleep 0.01 in + aux () in + aux () + +(* +-----------------------------------------------------------------+ + | Message handling | + +-----------------------------------------------------------------+ *) + +let handle_message looker (timestamp, message) = + match message with + | Kill "see_coin" -> + exit 0 + | _ -> + () + +(* +-----------------------------------------------------------------+ + | Command-line arguments | + +-----------------------------------------------------------------+ *) + +let fork = ref true + +let options = Arg.align [ + "-no-fork", Arg.Clear fork, " Run in foreground"; + "-calibration", Arg.String (fun s -> calibration_file:=Some s), "calibration config file"; + "-cam", Arg.String (fun s -> calibration_file:=Some s), "-calibration"; + "-homography", Arg.String (fun s -> homography_file:=Some s), "homography config file"; + "-h", Arg.String (fun s -> homography_file:=Some s), "-homography"; + "-color", Arg.String (fun s -> color_filter_file:=Some s), "color filter config file"; + "-c", Arg.String (fun s -> color_filter_file:=Some s), "-color"; +] + +let usage = "\ +Usage: krobot-see-coin [options] +options are:" + +(* +-----------------------------------------------------------------+ + | Entry point | + +-----------------------------------------------------------------+ *) + +lwt () = + Arg.parse options ignore usage; + + (* Display all informative messages. *) + Lwt_log.append_rule "*" Lwt_log.Info; + + (* Open the krobot bus. *) + lwt bus = Krobot_bus.get () in + + (* Fork if not prevented. *) + if !fork then Lwt_daemon.daemonize (); + + let looker = () in + + (* Handle krobot message. *) + E.keep (E.map (handle_message looker) (Krobot_bus.recv bus)); + + (* Kill any running planner. *) + lwt () = Krobot_bus.send bus (Unix.gettimeofday (), Krobot_bus.Kill "see_coin") in + +(* + (* Ask for initial parameters. *) + lwt () = Krobot_bus.send bus (Unix.gettimeofday (), Send) in +*) + + lwt vision = init_capture () in + + (* Loop forever. *) + loop bus vision diff --git a/info/control2011/src/tools/krobot_viewer.ml b/info/control2011/src/tools/krobot_viewer.ml index 7d4b629..92af2d6 100644 --- a/info/control2011/src/tools/krobot_viewer.ml +++ b/info/control2011/src/tools/krobot_viewer.ml @@ -55,6 +55,9 @@ type viewer = { mutable objects : vertice list; (* The objects on the table. *) + + mutable coins : vertice list; + (* The coins on the table *) } (* +-----------------------------------------------------------------+ @@ -69,6 +72,7 @@ type color = | Blue | Yellow | Purple + | Brown let set_color ctx color = let r, g, b = match color with @@ -79,6 +83,7 @@ let set_color ctx color = | Blue -> (0., 59., 128.) | Yellow -> (252., 189., 31.) | Purple -> (128., 0., 128.) + | Brown -> (175., 89., 67.) in Cairo.set_source_rgb ctx (r /. 255.) (g /. 255.) (b /. 255.) @@ -138,96 +143,89 @@ let draw viewer = (* Draw the viewer background *) Cairo.rectangle ctx 0. 0. world_width world_height; - set_color ctx Green; + set_color ctx Blue; Cairo.fill ctx; (* Draw the starting areas *) - Cairo.rectangle ctx 0. (world_height -. 0.4) 0.4 0.4; - set_color ctx Red; + Cairo.rectangle ctx 0. (world_height -. 0.5) 0.5 0.5; + set_color ctx Purple; Cairo.fill ctx; - Cairo.rectangle ctx (world_width -. 0.4) (world_height -. 0.4) 0.4 0.4; - set_color ctx Blue; + Cairo.rectangle ctx (world_width -. 0.5) (world_height -. 0.5) 0.5 0.5; + set_color ctx Red; Cairo.fill ctx; - (* Draw the paving *) - for i = 0 to 5 do - for j = 0 to 5 do - let x = 0.45 +. 0.35 *. float i - and y = 0.35 *. float j in - Cairo.rectangle ctx x y 0.35 0.35; - set_color ctx (if (i + j) mod 2 = 0 then Red else Blue); - Cairo.fill ctx - done - done; - - (* Draw the bands *) + (* draw black lines *) +(* + Cairo.move_to ctx 0.5; + Cairo.line_to ctx (world_height -. 0.45) (0.5 +. 0.15); + Cairo.line_to ctx 0. (0.5 +. 0.15); +*) + Cairo.move_to ctx 0.5 (world_height -. 0.45); + Cairo.line_to ctx (0.5 +. 0.15) (world_height -. 0.45); + Cairo.line_to ctx (0.5 +. 0.15) 0.; + Cairo.move_to ctx (world_width -. 0.5) (world_height -. 0.45); + Cairo.line_to ctx (world_width -. (0.5 +. 0.15)) (world_height -. 0.45); + Cairo.line_to ctx (world_width -. (0.5 +. 0.15)) 0.; set_color ctx Black; + Cairo.set_line_width ctx (5. /. scale); + Cairo.stroke ctx; - Cairo.rectangle ctx 0.4 0. 0.05 world_height; - Cairo.fill ctx; - - Cairo.rectangle ctx (world_width -. 0.45) 0. 0.05 world_height; - Cairo.fill ctx; - - Cairo.rectangle ctx 0.45 0.33 0.7 0.02; + (* draw the homes *) + Cairo.move_to ctx 0. 0.; + Cairo.line_to ctx 0.325 0.; + Cairo.line_to ctx 0.4 (world_height -. 0.5); + Cairo.line_to ctx 0. (world_height -. 0.5); + set_color ctx Brown; Cairo.fill ctx; - Cairo.rectangle ctx (world_width -. 1.15) 0.33 0.7 0.02; + Cairo.move_to ctx world_width 0.; + Cairo.line_to ctx (world_width -. 0.325) 0.; + Cairo.line_to ctx (world_width -. 0.4) (world_height -. 0.5); + Cairo.line_to ctx world_width (world_height -. 0.5); + set_color ctx Brown; Cairo.fill ctx; - Cairo.rectangle ctx 1.13 0. 0.02 0.35; - Cairo.fill ctx; + Cairo.set_antialias ctx Cairo.ANTIALIAS_DEFAULT; - Cairo.rectangle ctx (world_width -. 1.15) 0. 0.02 0.35; + (* Draw plages *) + Cairo.arc ctx 1.5 world_height 0.4 pi (2.*.pi); + set_color ctx Yellow; Cairo.fill ctx; - Cairo.rectangle ctx 0.45 0. 0.7 0.12; + Cairo.arc ctx 1.5 world_height 0.3 pi (2.*.pi); + set_color ctx Green; Cairo.fill ctx; - Cairo.rectangle ctx (world_width -. 1.15) 0. 0.7 0.12; + Cairo.arc ctx (0.64 +. 0.477) (world_height -. 1.) 0.3 0. (2.*.pi); + set_color ctx Yellow; Cairo.fill ctx; - Cairo.rectangle ctx 0.45 0. 0.02 0.25; + Cairo.arc ctx (world_width -. (0.64 +. 0.477)) (world_height -. 1.) 0.3 0. (2.*.pi); + set_color ctx Yellow; Cairo.fill ctx; - Cairo.rectangle ctx (world_width -. 0.47) 0. 0.02 0.25; + Cairo.rectangle ctx (0.64 +. 0.477) 0.75 0.8 0.5; + set_color ctx Yellow; Cairo.fill ctx; - Cairo.move_to ctx 0. (world_height -. 0.4); - Cairo.rel_line_to ctx 0.4 0.; - Cairo.stroke ctx; - - Cairo.move_to ctx 0. (world_height -. 0.422); - Cairo.rel_line_to ctx 0.4 0.; - Cairo.stroke ctx; - - Cairo.move_to ctx (world_width -. 0.4) (world_height -. 0.4); - Cairo.rel_line_to ctx 0.4 0.; - Cairo.stroke ctx; - - Cairo.move_to ctx (world_width -. 0.4) (world_height -. 0.422); - Cairo.rel_line_to ctx 0.4 0.; - Cairo.stroke ctx; - - Cairo.set_antialias ctx Cairo.ANTIALIAS_DEFAULT; - - (* Draw circles on bonus cases *) - Cairo.arc ctx 0.975 0.875 0.05 0. (2. *. pi); - Cairo.fill ctx; - - Cairo.arc ctx 0.975 1.575 0.05 0. (2. *. pi); + Cairo.arc ctx 1.5 0.24 0.55 (pi /. 4.) (3.*.pi/.4.); + set_color ctx Blue; Cairo.fill ctx; - Cairo.arc ctx 2.025 0.875 0.05 0. (2. *. pi); + Cairo.arc ctx 1.5 (world_height -. 0.24) 0.55 (5. *. pi /. 4.) (7.*.pi/.4.); + set_color ctx Blue; Cairo.fill ctx; - Cairo.arc ctx 2.025 1.575 0.05 0. (2. *. pi); + Cairo.arc ctx (0.64 +. 0.477) (world_height -. 1.) 0.2 0. (2.*.pi); + set_color ctx Green; Cairo.fill ctx; - Cairo.arc ctx 1.325 0.175 0.05 0. (2. *. pi); + Cairo.arc ctx (world_width -. (0.64 +. 0.477)) (world_height -. 1.) 0.2 0. (2.*.pi); + set_color ctx Green; Cairo.fill ctx; - Cairo.arc ctx 1.675 0.175 0.05 0. (2. *. pi); + Cairo.arc ctx 1.5 1. 0.1 0. (2.*.pi); + set_color ctx Green; Cairo.fill ctx; (* Draw objects *) @@ -242,6 +240,18 @@ let draw viewer = Cairo.stroke ctx) viewer.objects; + (* Draw coins *) + List.iter + (fun { x; y } -> + set_color ctx White; + Cairo.arc ctx x y Krobot_config.coin_radius 0. (2. *. pi); + Cairo.fill ctx; + + set_color ctx Black; + Cairo.arc ctx x y Krobot_config.coin_radius 0. (2. *. pi); + Cairo.stroke ctx) + viewer.coins; + (* Draw the robot and the ghost *) List.iter (fun (state, alpha) -> @@ -450,6 +460,15 @@ let handle_message viewer (timestamp, message) = viewer.objects <- l; queue_draw viewer + | Coins l -> + viewer.coins <- + List.map + (fun v -> + let v = [|v.x;v.y;1.|] in + let v = mult (rot_mat viewer.state.theta) v in + { x = v.(0); y = v.(1) }) l; + queue_draw viewer + | _ -> () @@ -511,6 +530,7 @@ lwt () = statusbar_context = ui#statusbar#new_context ""; motor_status = (false, false, false, false); objects = []; + coins = []; } in (* Handle messages. *) diff --git a/info/vision/camlcv/_oasis b/info/vision/camlcv/_oasis index b4c3985..198848e 100644 --- a/info/vision/camlcv/_oasis +++ b/info/vision/camlcv/_oasis @@ -29,10 +29,10 @@ Library "cv" CvHighGui CSources: cv_caml.c - CCopt: -x c++ -O2 + CCopt: -g -x c++ -O2 CClib: -lstdc++ XMETADescription: Core Opencv - BuildDepends: bigarray + BuildDepends: bigarray, str Executable "leak" Path: test/ @@ -81,3 +81,33 @@ Executable "test_calib" MainIs: test_calib.ml Install: false BuildDepends: cv + +Executable "test_homography" + Path: test/ + MainIs: test_homography.ml + Install: false + BuildDepends: cv + +Executable "test_detect_ellipse" + Path: test/ + MainIs: test_detect_ellipse.ml + Install: false + BuildDepends: cv + +Executable "test_houghLines" + Path: test/ + MainIs: test_houghLines.ml + Install: false + BuildDepends: cv + +Executable "test_contour_canny" + Path: test/ + MainIs: test_contour_canny.ml + Install: false + BuildDepends: cv + +Executable "test_detect_lines" + Path: test/ + MainIs: test_detect_lines.ml + Install: false + BuildDepends: cv diff --git a/info/vision/camlcv/_tags b/info/vision/camlcv/_tags index 5e875f3..763c3e7 100644 --- a/info/vision/camlcv/_tags +++ b/info/vision/camlcv/_tags @@ -1,5 +1,5 @@ # OASIS_START -# DO NOT EDIT (digest: c93fc9a48b0322812d7d9f91a98e5b8f) +# DO NOT EDIT (digest: dbce26cf07aa2393b0384ca639ce129c) # Ignore VCS directories, you can use the same kind of rule outside # OASIS_START/STOP if you want to exclude directories that contains # useless stuff for the build process @@ -23,33 +23,64 @@ "src/libcv_stubs.a": oasis_library_cv_cclib "src/dllcv_stubs.so": oasis_library_cv_cclib <src/cv.{cma,cmxa}>: use_libcv_stubs +<src/*.ml{,i}>: pkg_str <src/*.ml{,i}>: pkg_bigarray +"src/cv_caml.c": pkg_str "src/cv_caml.c": pkg_bigarray # Executable test_threshold "test/test_threshold.byte": use_cv +"test/test_threshold.byte": pkg_str "test/test_threshold.byte": pkg_bigarray +# Executable test_detect_lines +"test/test_detect_lines.byte": use_cv +"test/test_detect_lines.byte": pkg_str +"test/test_detect_lines.byte": pkg_bigarray # Executable leak "test/leak.byte": use_cv +"test/leak.byte": pkg_str "test/leak.byte": pkg_bigarray +# Executable test_houghLines +"test/test_houghLines.byte": use_cv +"test/test_houghLines.byte": pkg_str +"test/test_houghLines.byte": pkg_bigarray # Executable test_find_chessboard_corners "test/test_find_chessboard_corners.byte": use_cv +"test/test_find_chessboard_corners.byte": pkg_str "test/test_find_chessboard_corners.byte": pkg_bigarray +# Executable test_detect_ellipse +"test/test_detect_ellipse.byte": use_cv +"test/test_detect_ellipse.byte": pkg_str +"test/test_detect_ellipse.byte": pkg_bigarray # Executable test_improcess "test/test_improcess.byte": use_cv +"test/test_improcess.byte": pkg_str "test/test_improcess.byte": pkg_bigarray # Executable test_good_feature_to_track "test/test_good_feature_to_track.byte": use_cv +"test/test_good_feature_to_track.byte": pkg_str "test/test_good_feature_to_track.byte": pkg_bigarray +# Executable test_homography +"test/test_homography.byte": use_cv +"test/test_homography.byte": pkg_str +"test/test_homography.byte": pkg_bigarray # Executable test_drawing "test/test_drawing.byte": use_cv +"test/test_drawing.byte": pkg_str "test/test_drawing.byte": pkg_bigarray # Executable test_split "test/test_split.byte": use_cv +"test/test_split.byte": pkg_str "test/test_split.byte": pkg_bigarray +# Executable test_contour_canny +"test/test_contour_canny.byte": use_cv +"test/test_contour_canny.byte": pkg_str +"test/test_contour_canny.byte": pkg_bigarray # Executable test_calib "test/test_calib.byte": use_cv +"test/test_calib.byte": pkg_str "test/test_calib.byte": pkg_bigarray <test/*.ml{,i}>: use_cv +<test/*.ml{,i}>: pkg_str <test/*.ml{,i}>: pkg_bigarray # OASIS_STOP <src/*>: use_C_opencv diff --git a/info/vision/camlcv/myocamlbuild.ml b/info/vision/camlcv/myocamlbuild.ml index f231df6..8a82ba6 100644 --- a/info/vision/camlcv/myocamlbuild.ml +++ b/info/vision/camlcv/myocamlbuild.ml @@ -1,5 +1,5 @@ (* OASIS_START *) -(* DO NOT EDIT (digest: 4a00093589bdfb2586c46078313938d7) *) +(* DO NOT EDIT (digest: 956f5288d32a7a1c8abb0d0365a3324e) *) module OASISGettext = struct # 21 "/media/data/ocaml/oasis/src/oasis/OASISGettext.ml" @@ -556,6 +556,8 @@ let package_default = S [ A "-ccopt"; + A "-g"; + A "-ccopt"; A "-x"; A "-ccopt"; A "c++"; @@ -574,10 +576,12 @@ let package_default = let dispatch_default = MyOCamlbuildBase.dispatch_default package_default;; -# 578 "myocamlbuild.ml" +# 580 "myocamlbuild.ml" (* OASIS_STOP *) open Ocamlbuild_plugin +let () = Ocamlbuild_pack.Log.classic_display := true + let pkg_config flags package = with_temp_file "lwt" "pkg-config" (fun tmp -> @@ -593,6 +597,8 @@ let define_c_library ?(cplusplus=false) ~name ~c_name () = (* Add flags for linking with the C library: *) flag ["ocamlmklib"; "c"; tag] & S lib; + (* flag ["ocamlmklib"; "c"] & S[A"-verbose"]; *) + (* C stubs using the C library must be compiled with the library specifics flags: *) flag ["c"; "compile"; tag] & S(List.map (fun arg -> S[A"-ccopt"; arg]) opt); diff --git a/info/vision/camlcv/src/META b/info/vision/camlcv/src/META index 26e4895..320d2e5 100644 --- a/info/vision/camlcv/src/META +++ b/info/vision/camlcv/src/META @@ -1,8 +1,8 @@ # OASIS_START -# DO NOT EDIT (digest: 3f508b1b1a49417ae0d748f2f8bc10e1) +# DO NOT EDIT (digest: 74e425b91260fb882dfbdc09cc41cc88) version = "0.1" description = "Core Opencv" -requires = "bigarray" +requires = "bigarray str" archive(byte) = "cv.cma" archive(native) = "cv.cmxa" exists_if = "cv.cma" diff --git a/info/vision/camlcv/src/cvCore.ml b/info/vision/camlcv/src/cvCore.ml index 810965f..c77548b 100644 --- a/info/vision/camlcv/src/cvCore.ml +++ b/info/vision/camlcv/src/cvCore.ml @@ -6,6 +6,26 @@ type color_conversion_ (* int *) type channel_num_ = [ `Channel_1 | `Channel_2 | `Channel_3 | `Channel_4 ] type 'a channel_num = int +type cvScalar = float * float * float * float +type cvPoint = int * int +type cvPoint2D32f = float * float +type cvPoint3D32f = float * float * float +type cvPoint2D64f = float * float +type cvPoint3D64f = float * float * float +type cvSize = int * int +type cvTermCriteria = + { termcrit_iter : bool; + termcrit_epsilon : bool; + max_iter : int; + epsilon : float; } +type vec3f = float * float * float +type vec4f = float * float * float * float +type vec4i = int * int * int * int + +type vec3f_vect +type vec4f_vect +type vec4i_vect + let channel_1 = 1 let channel_2 = 2 let channel_3 = 3 @@ -215,6 +235,26 @@ external adaptive_threshold' : ('a,'b) iplImage -> ('d,'e) iplImage -> float -> external canny' : ([`Channel_1],[`U8]) iplImage -> ([`Channel_1],[`U8]) iplImage -> float -> float -> int -> unit = "ocaml_cvCanny" +external blur' : ('a,'b) iplImage -> ('a,'b) iplImage -> cvSize -> unit = "ocaml_blur" +external gaussian_blur' : ('a,'b) iplImage -> ('a,'b) iplImage -> cvSize -> float -> + float -> unit = "ocaml_GaussianBlur" +external median_blur' : ('a,'b) iplImage -> ('a,'b) iplImage -> int -> unit = "ocaml_medianBlur" + +external equalize_hist' : ([`Channel_1],[`U8]) iplImage -> + ([`Channel_1],[`U8]) iplImage -> unit = "ocaml_cvEqualizeHist" + +type morph_shape = + | MORPH_RECT + | MORPH_ELLIPSE + | MORPH_CROSS + +external dilate' : ('a,[`U8]) iplImage -> + ('a,[`U8]) iplImage -> morph_shape -> cvSize -> int -> unit + = "ocaml_dilate" + +external erode' : ('a,[`U8]) iplImage -> + ('a,[`U8]) iplImage -> morph_shape -> cvSize -> int -> unit + = "ocaml_erode" external cvSplit : ('a,'b) iplImage -> ([`Channel_1],'b) iplImage option -> ([`Channel_1],'b) iplImage option -> ([`Channel_1],'b) iplImage option -> @@ -278,14 +318,77 @@ let canny src ?(apertureSize=3) th1 th2 = canny' src dst th1 th2 apertureSize; dst +let blur ?(size=(3,3)) src = + let dst = create_image_from src in + blur' src dst size; + dst + +let gaussian_blur ?(size=(3,3)) src sigmaX sigmaY = + let dst = create_image_from src in + gaussian_blur' src dst size sigmaX sigmaY; + dst + +let median_blur ?(size=3) src = + let dst = create_image_from src in + median_blur' src dst size; + dst + +let equalize_hist src = + let dst = create_image_from src in + equalize_hist' src dst; + dst + +let dilate ?(iter=1) ?(shape=MORPH_ELLIPSE) src size = + let dst = create_image_from src in + dilate' src dst shape size iter; + dst + +let erode ?(iter=1) ?(shape=MORPH_ELLIPSE) src size = + let dst = create_image_from src in + erode' src dst shape size iter; + dst + type image_data = (int, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array2.t external image_data : ('a,[`U8]) iplImage -> image_data = "ocaml_image_to_bigarray" +(* +let between src min max = + let dst = create_image_from ~channels:1 ~depth:8 src in + let data_src = image_data src in + let data_dst = image_data dst in + let x, y = Bigarray.Array2.dim1 data_src, + Bigarray.Array2.dim2 data_src in + for i = 0 to x - 1 do + for j = 0 to y - 1 do + let r = Bigarray.Array2.unsafe_get data_src i j in + Bigarray.Array2.unsafe_set data_dst i j (if r >= min && r < max then 255 else 0); + done + done; + dst +*) + external zero_image : ('a,'b) iplImage -> unit = "ocaml_cvZero" external clone_image : ('a,'b) iplImage -> ('a,'b) iplImage = "ocaml_cvCloneImage" +external copy' : ('a,'b) iplImage -> ('a,'b) iplImage -> ([`Channel_1],[`U8]) iplImage option -> unit + = "ocaml_cvCopy" + +let copy src mask = + let dst = create_image_from src in + zero_image dst; + copy' src dst mask; + dst + +external set : ('a,'b) iplImage -> cvScalar -> ([`Channel_1],[`U8]) iplImage option -> unit + = "ocaml_cvSet" + +let between src min max = + let i_max = threshold src (float max -. 1.) 255. CV_THRESH_BINARY_INV in + let i_min = threshold src (float min -. 1.) 255. CV_THRESH_BINARY in + copy i_max (Some i_min) + let create_image ~x ~y _type i = cvCreateImage (x,y) (get_cvType _type) i let convert_color' ~src ~dst color_conversion = @@ -299,27 +402,21 @@ let convert_color src color_conversion = cvCvtColor src dst (get_color_conversion color_conversion); dst -type cvScalar = float * float * float * float -type cvPoint = int * int -type cvPoint2D32f = float * float -type cvPoint3D32f = float * float * float -type cvPoint2D64f = float * float -type cvPoint3D64f = float * float * float -type cvSize = int * int -type cvTermCriteria = - { termcrit_iter : bool; - termcrit_epsilon : bool; - max_iter : int; - epsilon : float; } -type vec3f = float * float * float - -type vec3f_vect - external create_vec3f_vect : unit -> vec3f_vect = "ocaml_create_Vec3f_vector" external vec3f_vect_size : vec3f_vect -> int = "ocaml_vector_size_Vec3f" external vec3f_vect_add : vec3f_vect -> vec3f -> unit = "ocaml_vector_add_Vec3f" external vec3f_vect_get : vec3f_vect -> int -> vec3f = "ocaml_vector_get_Vec3f" +external create_vec4f_vect : unit -> vec4f_vect = "ocaml_create_Vec4f_vector" +external vec4f_vect_size : vec4f_vect -> int = "ocaml_vector_size_Vec4f" +external vec4f_vect_add : vec4f_vect -> vec4f -> unit = "ocaml_vector_add_Vec4f" +external vec4f_vect_get : vec4f_vect -> int -> vec4f = "ocaml_vector_get_Vec4f" + +external create_vec4i_vect : unit -> vec4i_vect = "ocaml_create_Vec4i_vector" +external vec4i_vect_size : vec4i_vect -> int = "ocaml_vector_size_Vec4i" +external vec4i_vect_add : vec4i_vect -> vec4i -> unit = "ocaml_vector_add_Vec4i" +external vec4i_vect_get : vec4i_vect -> int -> vec4i = "ocaml_vector_get_Vec4i" + external cvCircle : ('a,[`U8]) iplImage -> cvPoint -> int -> cvScalar -> int -> unit = "ocaml_cvCircle" external cvEllipse : ('a,[`U8]) iplImage -> cvPoint -> cvSize -> float -> float -> float -> cvScalar -> int -> unit = @@ -344,7 +441,11 @@ let circle dst ?(thickness=1) ?(color=blue) center radius = let ellipse dst ?(thickness=1) ?(color=blue) ?(angle=0.) ?(start_angle=0.) ?(end_angle=360.) center size = - cvEllipse dst center size angle start_angle end_angle (scalar_color color) thickness + let (x,y) = center in + let (w,h) = size in + (* try to avoid segfault in opencv drawing... *) + if x > 10000 || y > 10000 || w > 10000 || h > 10000 then () + else cvEllipse dst center size angle start_angle end_angle (scalar_color color) thickness type ellipse = { ellipse_center : float * float; @@ -359,8 +460,9 @@ let ellipse' dst ?thickness ?color ?start_angle ?end_angle ellipse_angle = angle; } = ellipse dst ?thickness ?color ?start_angle ?end_angle + ~angle (int_of_float x, int_of_float y) - (int_of_float w, int_of_float h) + (int_of_float (w/.2.), int_of_float (h/.2.)) let rectangle dst ?(thickness=1) ?(color=blue) p1 p2 = cvRectangle dst p1 p2 (scalar_color color) thickness @@ -394,7 +496,7 @@ type contour_approximation_method = type cvSeq external cvFindContours : ([`Channel_1],[`U8]) iplImage -> cvMemStorage -> - contour_retrieval_mode -> contour_approximation_method -> cvPoint -> cvSeq = + contour_retrieval_mode -> contour_approximation_method -> cvPoint -> cvSeq option = "ocaml_cvFindContours" type cvSeq_info = { @@ -406,40 +508,60 @@ type cvSeq_info = { external cvSeq_info : cvSeq -> cvSeq_info = "ocaml_CvSeq_info" -type seq = { +type contour = { seq_stor : cvMemStorage; seq : cvSeq; } -type seq_info = { - h_prev : seq option; - h_next : seq option; - v_prev : seq option; - v_next : seq option; +type contour_info = { + h_prev : contour option; + h_next : contour option; + v_prev : contour option; + v_next : contour option; } let add_stor s = function | None -> None | Some v -> Some { seq_stor = s; seq = v } -let seq_info seq = +let contour_info seq = let info = cvSeq_info seq.seq in { h_prev = add_stor seq.seq_stor info.cv_h_prev; h_next = add_stor seq.seq_stor info.cv_h_next; v_prev = add_stor seq.seq_stor info.cv_v_prev; v_next = add_stor seq.seq_stor info.cv_v_next; } +type contours = Contour of (contour * contours list) + +let rec contour_list contour = + let { h_next } = contour_info contour in + match h_next with + | None -> [contour] + | Some v -> contour::(contour_list v) + +let rec contours c = + match c with + | None -> [] + | Some c -> + let l = contour_list c in + let aux c = Contour (c,contours (contour_info c).v_next) in + List.map aux l + let find_contours ?(mode=CV_RETR_LIST) ?(meth=CV_CHAIN_APPROX_SIMPLE) image = let stor = create_CvMemStorage () in - let cvSeq = cvFindContours image stor mode meth (0,0) in - { seq_stor = stor; - seq = cvSeq } + match cvFindContours image stor mode meth (0,0) with + | Some cvSeq -> + Some { seq_stor = stor; + seq = cvSeq } + | None -> None external cvDrawContours : ('a,[`U8]) iplImage -> cvSeq -> cvScalar -> cvScalar -> int -> int -> cvPoint -> unit = "ocaml_cvDrawContours_bytecode" "ocaml_cvDrawContours" -let draw_contours image seq in_color out_color level thickness offset = - cvDrawContours image seq.seq in_color out_color level thickness offset +let draw_contours ?(in_color=red) ?(out_color=green) ?(thickness=1) ?(offset=(0,0)) + ?(level=0) image seq = + cvDrawContours image seq.seq + (scalar_color in_color) (scalar_color out_color) level thickness offset external cvFitEllipse2 : cvSeq -> (float * float * float * float * float) option = "ocaml_cvFitEllipse2" @@ -482,6 +604,17 @@ let houghCircles img ?(param1=100.) ?(param2=100.) ?(minRadius=0) ?(maxRadius=0) houghCircles' img vec dp minDist param1 param2 minRadius maxRadius; Array.init (vec3f_vect_size vec) (fun i -> vec3f_vect_get vec i) +external houghLinesP' : + ('a,[`U8]) iplImage -> + vec4i_vect -> + float -> float -> int -> float -> float -> unit + = "ocaml_HoughLinesP_bytecode" "ocaml_HoughLinesP" + +let houghLinesP img ?(minLineLength=0.) ?(maxLineGap=0.) rho theta threshold = + let vec = create_vec4i_vect () in + houghLinesP' img vec rho theta threshold minLineLength maxLineGap; + Array.init (vec4i_vect_size vec) (fun i -> vec4i_vect_get vec i) + type calib_cb = | CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_NORMALIZE_IMAGE @@ -658,3 +791,69 @@ external cvFindHomography : [`Channel_1] cvMat_float64 -> unit = "ocaml_cvFindHomography" + +let find_homography ~obj_pos ~img_pos = + let convert a = + Bigarray.Array3.of_array Bigarray.float64 Bigarray.c_layout + [|Array.map (fun (x,y) -> [|x;y|]) a|] in + let out = + Bigarray.Array3.of_array Bigarray.float64 Bigarray.c_layout + (Array.init 3 (fun _ -> Array.init 3 (fun _ -> [|0.|]))) in + cvFindHomography (convert obj_pos) (convert img_pos) out; + Array.init 3 (fun i -> Array.init 3 (fun j -> out.{i,j,0})) + +let replace_comma = + let r = Str.regexp "," in + Str.global_replace r "." + +let file_string file = + let file = open_in file in + let l = in_channel_length file in + let s = String.create l in + ignore(Pervasives.input file s 0 l); + s + +let load_calibration_file file = + let f s = Scanf.sscanf (replace_comma s) " %f %f %f\n %f %f %f\n %f %f %f\n\n %f %f %f %f %f" + (fun v11 v12 v13 v21 v22 v23 v31 v32 v33 + v1 v2 v3 v4 v5 -> + [|[|v11;v12;v13|]; + [|v21;v22;v23|]; + [|v31;v32;v33|]|], + [|v1;v2;v3;v4;v5|]) in + + let s = file_string file in + f s + +let load_homography_file file = + let f s = Scanf.sscanf (replace_comma s) " %f %f %f\n %f %f %f\n %f %f %f" + (fun v11 v12 v13 v21 v22 v23 v31 v32 v33 -> + [|[|v11;v12;v13|]; + [|v21;v22;v23|]; + [|v31;v32;v33|]|]) in + + let s = file_string file in + f s + + +external cvInvert : + [`Channel_1] cvMat_float64 -> + [`Channel_1] cvMat_float64 -> + float + = "ocaml_cvInvert" + +let invert src = + let src' = Array.map (fun e -> Array.map (fun x -> [|x|]) e) src in + let src_ba = Bigarray.Array3.of_array Bigarray.float64 Bigarray.c_layout src' in + let i = Bigarray.Array3.dim1 src_ba in + let j = Bigarray.Array3.dim2 src_ba in + let dst_ba = Bigarray.Array3.create Bigarray.float64 Bigarray.c_layout j i 1 in + let det = cvInvert src_ba dst_ba in + let dst = Array.init j + (fun x -> Array.init i (fun y -> dst_ba.{x,y,0})) in + det, dst + +let mult m v = + Array.init (Array.length m) + (fun k -> Array.fold_left (+.) 0. + (Array.mapi (fun i n -> v.(i) *. n) m.(k))) diff --git a/info/vision/camlcv/src/cvCore.mli b/info/vision/camlcv/src/cvCore.mli index 3aa6239..9c559f3 100644 --- a/info/vision/camlcv/src/cvCore.mli +++ b/info/vision/camlcv/src/cvCore.mli @@ -12,6 +12,8 @@ type cvTermCriteria = max_iter : int; epsilon : float; } type vec3f = float * float * float +type vec4f = float * float * float * float +type vec4i = int * int * int * int type ('chan_num,'depth) iplImage @@ -35,6 +37,15 @@ val create_image : x:int -> y:int -> 'depth image_depth -> 'chan_num channel_num val clone_image : ('a,'b) iplImage -> ('a,'b) iplImage val zero_image : ('a,'b) iplImage -> unit +val copy' : ('a,'b) iplImage -> ('a,'b) iplImage -> + ([`Channel_1],[`U8]) iplImage option -> unit + +val copy : ('a,'b) iplImage -> + ([`Channel_1],[`U8]) iplImage option -> ('a,'b) iplImage + +val set : ('a,'b) iplImage -> cvScalar -> + ([`Channel_1],[`U8]) iplImage option -> unit + val image_size : ('a,'b) iplImage -> int * int val image_channels : ('a,'b) iplImage -> int val image_depth : ('a,'b) iplImage -> int @@ -109,6 +120,9 @@ val adaptive_threshold : ([`Channel_1],'b) iplImage -> float -> adaptive_method -> threshold_type -> int -> float -> ([`Channel_1],'b) iplImage (** [adaptive_threshold src maxValue adaptiveMethod thresholdType blockSize param1] *) +val between : ([`Channel_1],[`U8]) iplImage -> int -> int -> ([`Channel_1],[`U8]) iplImage +(** [between src min max] is 255 for each point p when min <= p < max *) + (** edge detection *) val canny' : ([`Channel_1],[`U8]) iplImage -> ([`Channel_1],[`U8]) iplImage -> @@ -118,6 +132,47 @@ val canny : ([ `Channel_1 ], [ `U8 ]) iplImage -> float -> float -> ([ `Channel_1 ], [ `U8 ]) iplImage (** [canny src threshold1 threshold2] *) +(** image processing *) + +val blur' : ('a,'b) iplImage -> ('a,'b) iplImage -> cvSize -> unit +val blur : ?size:cvSize -> ('a, 'b) iplImage -> ('a, 'b) iplImage + +val gaussian_blur' : ('a,'b) iplImage -> ('a,'b) iplImage -> cvSize -> float -> + float -> unit +val gaussian_blur : ?size:cvSize -> ('a,'b) iplImage -> float -> + float -> ('a,'b) iplImage + +val median_blur' : ('a,'b) iplImage -> ('a,'b) iplImage -> int -> unit +val median_blur : ?size:int -> ('a, 'b) iplImage -> ('a, 'b) iplImage + +val equalize_hist' : ([`Channel_1],[`U8]) iplImage -> + ([`Channel_1],[`U8]) iplImage -> unit +val equalize_hist : ([`Channel_1],[`U8]) iplImage -> + ([`Channel_1],[`U8]) iplImage + +type morph_shape = + | MORPH_RECT + | MORPH_ELLIPSE + | MORPH_CROSS + +val dilate' : ('a, [ `U8 ]) iplImage -> + ('a, [ `U8 ]) iplImage -> + morph_shape -> cvSize -> int -> unit + +val erode' : ('a, [ `U8 ]) iplImage -> + ('a, [ `U8 ]) iplImage -> + morph_shape -> cvSize -> int -> unit + +val dilate : ?iter:int -> + ?shape:morph_shape -> + ('a, [ `U8 ]) iplImage -> + cvSize -> ('a, [ `U8 ]) iplImage + +val erode : ?iter:int -> + ?shape:morph_shape -> + ('a, [ `U8 ]) iplImage -> + cvSize -> ('a, [ `U8 ]) iplImage + (** drawing *) type color = int * int * int (** red, green, blue *) @@ -188,22 +243,32 @@ type contour_approximation_method = | CV_CHAIN_APPROX_TC89_KCOS | CV_LINK_RUNS -type seq +type contour -type seq_info = { - h_prev : seq option; - h_next : seq option; - v_prev : seq option; - v_next : seq option; +type contour_info = { + h_prev : contour option; + h_next : contour option; + v_prev : contour option; + v_next : contour option; } -val seq_info : seq -> seq_info +type contours = Contour of (contour * contours list) + +val contours : contour option -> contours list + +val contour_info : contour -> contour_info val find_contours : ?mode:contour_retrieval_mode -> ?meth:contour_approximation_method -> - ([`Channel_1],[`U8]) iplImage -> seq + ([`Channel_1],[`U8]) iplImage -> contour option -val draw_contours : ('a,[`U8]) iplImage -> seq -> cvScalar -> cvScalar -> int -> int -> cvPoint -> unit +val draw_contours : + ?in_color:color -> + ?out_color:color -> + ?thickness:int -> + ?offset:cvPoint -> + ?level:int -> + ('a, [ `U8 ]) iplImage -> contour -> unit -val fit_ellipse : seq -> ellipse option +val fit_ellipse : contour -> ellipse option val good_features_to_track : ([ `Channel_1 ], 'a) iplImage -> @@ -221,6 +286,12 @@ val good_features_to_track : ?minRadius:int -> ?maxRadius:int -> float -> float -> vec3f array (** [houghCircles img dp minDist] *) + val houghLinesP : + ('a, [ `U8 ]) iplImage -> + ?minLineLength:float -> + ?maxLineGap:float -> float -> float -> int -> vec4i array +(** [houghLinesP img rho theta threshold] *) + type calib_cb = | CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_NORMALIZE_IMAGE @@ -249,21 +320,18 @@ val add_calibration_image : calibration -> ([ `Channel_1 ], [ `U8 ]) iplImage -> calibration val calibrate : calibration -> float * ( float array array * float array ) +val load_calibration_file : string -> ( float array array * float array ) +val load_homography_file : string -> float array array + type remap val init_undistort_map : cvSize -> ( float array array * float array ) -> remap val remap' : remap -> ('a, 'b) iplImage -> ('a, 'b) iplImage -> unit val remap : remap -> ('a, 'b) iplImage -> ('a, 'b) iplImage -type ('channel) cvMat_float32 = - (float, Bigarray.float32_elt, Bigarray.c_layout) Bigarray.Array3.t +val find_homography : obj_pos: (float*float) array -> img_pos: (float*float) array -> + float array array -type ('channel) cvMat_float64 = - (float, Bigarray.float64_elt, Bigarray.c_layout) Bigarray.Array3.t +val invert : float array array -> float * float array array -external cvFindHomography : - [`Channel_2] cvMat_float64 -> - [`Channel_2] cvMat_float64 -> - [`Channel_1] cvMat_float64 -> - unit - = "ocaml_cvFindHomography" +val mult : float array array -> float array -> float array diff --git a/info/vision/camlcv/src/cvHighGui.ml b/info/vision/camlcv/src/cvHighGui.ml index e10f58f..3fffc22 100644 --- a/info/vision/camlcv/src/cvHighGui.ml +++ b/info/vision/camlcv/src/cvHighGui.ml @@ -20,6 +20,8 @@ external cvLoadImage : string -> iscolor_ -> ('a,'b) iplImage = "ocaml_cvLoadIma let load_image file iscolor = cvLoadImage file (get_iscolor iscolor) +external save_image : string -> ('a,'b) iplImage -> int = "ocaml_cvSaveImage" + (* capture *) type cvCapture diff --git a/info/vision/camlcv/src/cvHighGui.mli b/info/vision/camlcv/src/cvHighGui.mli index 6e54b60..563d928 100644 --- a/info/vision/camlcv/src/cvHighGui.mli +++ b/info/vision/camlcv/src/cvHighGui.mli @@ -8,6 +8,7 @@ val load_color : [`Channel_3] load_color val load_grayscale : [`Channel_1] load_color val load_image : string -> 'depth load_color -> ('depth,[`U8]) iplImage +val save_image : string -> ('a,'b) iplImage -> int (** camera capture *) diff --git a/info/vision/camlcv/src/cv_caml.c b/info/vision/camlcv/src/cv_caml.c index a49aaf1..f7a0a55 100644 --- a/info/vision/camlcv/src/cv_caml.c +++ b/info/vision/camlcv/src/cv_caml.c @@ -35,6 +35,17 @@ catch (const cv::Exception &e) \ caml_failwith(e.what()); \ } +static value Val_some(value v) +{ + CAMLparam1(v); + CAMLlocal1(res); + res = caml_alloc(1,0); + Field(res,0) = v; + CAMLreturn(res); +} + +static value Val_none = Val_unit; + static Vec3f Vec3f_val(value v) { double v0 = Double_val(Field(v,0)); double v1 = Double_val(Field(v,1)); @@ -52,6 +63,42 @@ static value Val_Vec3f(Vec3f v) { CAMLreturn(res); } +static Vec4f Vec4f_val(value v) { + double v0 = Double_val(Field(v,0)); + double v1 = Double_val(Field(v,1)); + double v2 = Double_val(Field(v,2)); + double v3 = Double_val(Field(v,3)); + return (Vec4f(v0,v1,v2,v3)); +} + +static value Val_Vec4f(Vec4f v) { + CAMLparam0(); + CAMLlocal1(res); + res = caml_alloc_tuple(4); + for(int i = 0; i < 4; i++) { + Field(res,i) = caml_copy_double(v[i]); + } + CAMLreturn(res); +} + +static Vec4i Vec4i_val(value v) { + int v0 = Int_val(Field(v,0)); + int v1 = Int_val(Field(v,1)); + int v2 = Int_val(Field(v,2)); + int v3 = Int_val(Field(v,3)); + return (Vec4i(v0,v1,v2,v3)); +} + +static value Val_Vec4i(Vec4i v) { + CAMLparam0(); + CAMLlocal1(res); + res = caml_alloc_tuple(4); + for(int i = 0; i < 4; i++) { + Field(res,i) = Val_int(v[i]); + } + CAMLreturn(res); +} + /* c++ vector */ template <typename Type> @@ -158,6 +205,48 @@ extern "C" CAMLprim value ocaml_vector_get_Vec3f(value v, value x) CAMLreturn(Val_Vec3f(r)); } +extern "C" CAMLprim value ocaml_create_Vec4f_vector(value v) +{ + return(ocaml_create_vector<Vec4f>(v)); +} + +extern "C" CAMLprim value ocaml_vector_size_Vec4f(value v) +{ + return(ocaml_vector_size<Vec4f>(v)); +} + +extern "C" CAMLprim value ocaml_vector_add_Vec4f(value v, value x) +{ + return(ocaml_vector_add<Vec4f>(v,x,Vec4f_val(x))); +} +extern "C" CAMLprim value ocaml_vector_get_Vec4f(value v, value x) +{ + CAMLparam2(v,x); + Vec4f r = ocaml_vector_get<Vec4f>(v,x); + CAMLreturn(Val_Vec4f(r)); +} + +extern "C" CAMLprim value ocaml_create_Vec4i_vector(value v) +{ + return(ocaml_create_vector<Vec4i>(v)); +} + +extern "C" CAMLprim value ocaml_vector_size_Vec4i(value v) +{ + return(ocaml_vector_size<Vec4i>(v)); +} + +extern "C" CAMLprim value ocaml_vector_add_Vec4i(value v, value x) +{ + return(ocaml_vector_add<Vec4i>(v,x,Vec4i_val(x))); +} +extern "C" CAMLprim value ocaml_vector_get_Vec4i(value v, value x) +{ + CAMLparam2(v,x); + Vec4i r = ocaml_vector_get<Vec4i>(v,x); + CAMLreturn(Val_Vec4i(r)); +} + /* basic caml value conversions */ static CvScalar CvScalar_val(value v) { @@ -284,7 +373,7 @@ static CvMat CvMat_val(value v) { return (cvMat(rows, cols, type, data)); } -int cvType_table[] = { +uint cvType_table[] = { IPL_DEPTH_1U, IPL_DEPTH_8U, IPL_DEPTH_16U, @@ -410,16 +499,47 @@ extern "C" CAMLprim value ocaml_cvLoadImage(value vfile, value viscolor) CAMLreturn (res); } +extern "C" CAMLprim value ocaml_cvSaveImage(value vfile, value vimg) +{ + CAMLparam2 (vfile, vimg); + + int ret = cvSaveImage(String_val(vfile), + Image_val(vimg)->image); + + CAMLreturn (Val_int(ret)); +} + extern "C" CAMLprim value ocaml_cvCloneImage(value vimage) { CAMLparam1 (vimage); CAMLlocal1 (res); IplImage* image = cvCloneImage( Image_val(vimage)->image ); - if(image == 0) { caml_failwith("load_image: can't load image"); }; res = caml_alloc_IplImage(image); CAMLreturn (res); } +extern "C" CAMLprim value ocaml_cvCopy(value vsrc, value vdst, value vmask) +{ + CAMLparam3 (vsrc, vdst, vmask); + CvArr* mask = Is_long(vmask) ? NULL : Image_val(Field(vmask,0))->image; + ERRWRAP( + cvCopy(Image_val(vsrc)->image, + Image_val(vdst)->image, + mask)); + CAMLreturn (Val_unit); +} + +extern "C" CAMLprim value ocaml_cvSet(value vdst, value vval, value vmask) +{ + CAMLparam3 (vdst, vval, vmask); + CvArr* mask = Is_long(vmask) ? NULL : Image_val(Field(vmask,0))->image; + ERRWRAP( + cvSet(Image_val(vdst)->image, + CvScalar_val(vval), + mask)); + CAMLreturn (Val_unit); +} + extern "C" CAMLprim value ocaml_cvZero(value vimage) { CAMLparam1 (vimage); @@ -672,8 +792,10 @@ extern "C" CAMLprim value ocaml_set_int_var(value vvar, value vval) extern "C" CAMLprim value ocaml_cvCreateTrackbar(value vname, value vwindow, value vvar, value vmax) { CAMLparam4 (vname, vwindow, vvar, vmax); - int res = cvCreateTrackbar(String_val(vname), String_val(vwindow), - Int_var_val(vvar), Int_val(vmax), NULL); + int res; + ERRWRAP( + res = cvCreateTrackbar(String_val(vname), String_val(vwindow), + Int_var_val(vvar), Int_val(vmax), NULL)); CAMLreturn (Val_int(res)); } @@ -867,7 +989,65 @@ extern "C" CAMLprim value ocaml_cvCanny(value vimage, value vedges, CAMLreturn(Val_unit); } -/* +extern "C" CAMLprim value ocaml_cvEqualizeHist(value vsrc, value vdst) +{ + CAMLparam2 (vsrc, vdst); + + ERRWRAP( + cvEqualizeHist(Image_val(vsrc)->image, + Image_val(vdst)->image)); + CAMLreturn (Val_unit); +} + + +int morph_table[] = { + MORPH_RECT, + MORPH_ELLIPSE, + MORPH_CROSS +}; + +extern "C" CAMLprim value ocaml_dilate(value vsrc, value vdst, value shape, + value ksize, value viter) +{ + CAMLparam5 (vsrc, vdst, shape, ksize, viter); + + Mat sel = getStructuringElement(morph_table[Int_val(shape)], + CvSize_val(ksize)); + + Mat src = Mat(Image_val(vsrc)->image); + Mat dst = Mat(Image_val(vdst)->image); + + ERRWRAP( + dilate(src, + dst, + sel, + Point(-1,-1), + Int_val(viter))); + + CAMLreturn (Val_unit); +} + +extern "C" CAMLprim value ocaml_erode(value vsrc, value vdst, value shape, + value ksize, value viter) +{ + CAMLparam5 (vsrc, vdst, shape, ksize, viter); + + Mat sel = getStructuringElement(morph_table[Int_val(shape)], + CvSize_val(ksize)); + + Mat src = Mat(Image_val(vsrc)->image); + Mat dst = Mat(Image_val(vdst)->image); + + ERRWRAP( + erode(src, + dst, + sel, + Point(-1,-1), + Int_val(viter))); + + CAMLreturn (Val_unit); +} + extern "C" CAMLprim value ocaml_medianBlur(value vsrc, value vdst, value ksize) { CAMLparam3(vsrc, vdst, ksize); @@ -876,12 +1056,43 @@ extern "C" CAMLprim value ocaml_medianBlur(value vsrc, value vdst, value ksize) ERRWRAP( medianBlur(Mat(Image_val(vsrc)->image), - &dst, + dst, Int_val(ksize))); CAMLreturn(Val_unit); } -*/ + +extern "C" CAMLprim value ocaml_blur(value vsrc, value vdst, value ksize) +{ + CAMLparam3(vsrc, vdst, ksize); + + Mat dst = Mat(Image_val(vdst)->image); + + ERRWRAP( + blur(Mat(Image_val(vsrc)->image), + dst, + CvSize_val(ksize))); + + CAMLreturn(Val_unit); +} + +extern "C" CAMLprim value ocaml_GaussianBlur(value vsrc, value vdst, value ksize, + value sigmaX, value sigmaY) +{ + CAMLparam5(vsrc, vdst, ksize, sigmaX, sigmaY); + + Mat dst = Mat(Image_val(vdst)->image); + + ERRWRAP( + GaussianBlur(Mat(Image_val(vsrc)->image), + dst, + CvSize_val(ksize), + Double_val(sigmaX), + Double_val(sigmaY))); + + CAMLreturn(Val_unit); +} + extern "C" CAMLprim value ocaml_cvGoodFeaturesToTrack( value image, @@ -976,9 +1187,10 @@ extern "C" CAMLprim value ocaml_cvEllipse(value vimg, value vcenter, { CAMLparam5(vimg, vcenter, vaxes, vangle, vstart_angle); CAMLxparam3(vend_angle, vcolor, vthickness); + ERRWRAP( cvEllipse(Image_val(vimg)->image, CvPoint_val(vcenter), CvSize_val(vaxes), Double_val(vangle), Double_val(vstart_angle), Double_val(vend_angle), - CvScalar_val(vcolor), Int_val(vthickness), CV_AA, 0); + CvScalar_val(vcolor), Int_val(vthickness), CV_AA, 0)); CAMLreturn(Val_unit); } @@ -1061,7 +1273,12 @@ extern "C" CAMLprim value ocaml_cvFindContours(value vimg, value vstor, value vm contour_approximation_method_table[Int_val(vmethod)], CvPoint_val(voffset))); - res = caml_alloc_cvSeq(first_contour); + if(first_contour) { + res = Val_some(caml_alloc_cvSeq(first_contour)); + } + else { + res = Val_none; + } CAMLreturn(res); } @@ -1098,21 +1315,42 @@ extern "C" CAMLprim value ocaml_HoughCircles_bytecode( value * argv, int argn ) argv[4], argv[5], argv[6], argv[7] ); } -static value Val_some(value v) +/* houghlines */ + +extern "C" CAMLprim value ocaml_HoughLinesP(value vimg, + value vlines, + value rho, + value theta, + value threshold, + value minLineLength, + value maxLineGap) { - CAMLparam1(v); - CAMLlocal1(res); - res = caml_alloc(1,0); - Field(res,0) = v; - CAMLreturn(res); + CAMLparam5( vimg, vlines, rho, theta, threshold ); + CAMLxparam2( minLineLength, maxLineGap ); + + ERRWRAP( + HoughLinesP(Mat(Image_val(vimg)->image), + *Vector_val<Vec4i>(vlines), + Double_val(rho), + Double_val(theta), + Int_val(threshold), + Double_val(minLineLength), + Double_val(maxLineGap))); + + CAMLreturn(Val_unit); } -static value Val_none = Val_unit; +extern "C" CAMLprim value ocaml_HoughLinesP_bytecode( value * argv, int argn ) +{ + return ocaml_HoughLinesP( argv[0], argv[1], argv[2], argv[3], + argv[4], argv[5], argv[6] ); +} extern "C" CAMLprim value ocaml_CvSeq_info(value vseq) { CAMLparam1(vseq); CAMLlocal1(res); + CvSeq *seq = CvSeq_val(vseq); res = caml_alloc_tuple(4); @@ -1160,7 +1398,8 @@ extern "C" CAMLprim value ocaml_cvFitEllipse2( value vpoints ) res = caml_alloc_tuple(5); CvSeq *points = CvSeq_val(vpoints); if(points->total < 5) CAMLreturn(Val_none); - CvBox2D box = cvFitEllipse2(points); + CvBox2D box; + ERRWRAP (box = cvFitEllipse2(points)); Field(res,0) = caml_copy_double(box.center.x); Field(res,1) = caml_copy_double(box.center.y); Field(res,2) = caml_copy_double(box.size.width); @@ -1333,3 +1572,15 @@ extern "C" CAMLprim value ocaml_cvFindHomography( value vsrc, value vdst, value CAMLreturn(Val_unit); } + +extern "C" CAMLprim value ocaml_cvInvert( value vsrc, value vdst... [truncated message content] |