(*
* Copyright (c) 2005, 2006, 2007 Abram Hindle
*
* This file is part of CaptchaBreaker
* CaptchaBreaker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
* Foobar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*)
(* Machine Learning Shit, Extractors etc. *)
open Shape;;
open Images;;
open OImages;;
open Fft;;
open Abez;;
(* Features we want to add,
* count pts
* centroid
* x mid point
* y mid point
* aspect
* sum columns
* FFT
* End points
* loops
*)
let fft = new jfft;;
let b_w_h h =
let height = h#height in
let width = h#width in
(width,height)
;;
let hget bmp x y =
let c = bmp#get x y in
1.0 -. (float_of_int (c.r )) /. 255.
;;
let cnt_pts b =
let (w,h) = b_w_h b in
let o = ref 0. in
for y = 0 to (h - 1) do
for x = 0 to (w - 1) do
o := !o +. (hget b x y)
done;
done;
((!o),(float_of_int (w*h)))
;;
(* centroid, and normalized centroid *)
let centroid b =
let (w,h) = b_w_h b in
let xo = ref 0. in
let yo = ref 0. in
let fi = float_of_int in
for y = 0 to (h - 1) do
for x = 0 to (w - 1) do
let g = hget b x y in
yo := !yo +. (fi y) *. g ;
xo := !xo +. (fi x) *. g ;
done;
done;
let fh1 = fi (h - 1) in
let fw1 = fi (w - 1) in
yo := !yo /. (fh1) -. fh1 /. 2.0;
xo := !xo /. (fw1) -. fw1 /. 2.0;
(!xo , !yo, (!xo /. (fw1 /. 2.0)), (!yo /. (fh1 /. 2.0)))
;;
let normalized_cnt_pts b =
let (points,total_points) = cnt_pts b in
points /. total_points
;;
let get_aspect (_,_,x,y) b =
let (w,h) = b_w_h b in
let fw = (float_of_int ( w - 1)) in
let fh = (float_of_int ( h - 1)) in
(y *. fh +. fh /. 2.0) /. ( x *. fw +. fw /. 2.0)
;;
let resample_to w h bmp =
let (hw,hh) = b_w_h bmp in
let arr = Array.create (w * h) 0. in
let arrget i =
arr.(i)
in
let arradd i x =
arr.(i) <- arr.(i) +. x;
in
let index x y w = y * w + x in
for y = 0 to (hh - 1) do
for x = 0 to (hw - 1) do
let y' = y * (h - 1) / (hh - 1) in
let x' = x * (w - 1) / (hw - 1)in
let dx = hget bmp x y in
arradd (index x' y' w) dx;
done;
done;
arr
;;
let normalized_subset w h bmp =
let index x y w = y * w + x in
let arr = resample_to w h bmp in
let arrdiv i x =
arr.(i) <- arr.(i) /. x;
in
let arrget x y=
arr.(index x y w)
in
for y = 0 to (h - 1) do
let total = ref 0. in
for x = 0 to (w - 1) do
total := !total +. (arrget x y)
done;
if ((!total *. !total) > 0.0000000001) then
for x = 0 to (w - 1) do
arrdiv (index x y w) !total;
done;
done;
Array.to_list arr
;;
let resample_to_aspect w h bmp =
let (hw,hh) = b_w_h bmp in
let fi = float_of_int in
let l = w * h in
let arr = Array.create l (0.,0) in
let outarr = Array.create l 0. in
let index x y = x + w * y in
let aspect = (fi hh) /. (fi hw) in
let outset x y v =
outarr.(index x y) <- v
in
let arrget x y =
arr.(index x y)
in
let arradd x y dx =
let i = index x y in
if (i < l) then
let (v,c) = arr.(i) in
arr.(i) <- (v+.dx,c+1)
in
let xw = int_of_float ((fi (w)) /. aspect) in
let yh = int_of_float ((fi (h)) *. aspect) in
let f h' w' =
let yoff = (h - h')/2 in
let xoff = (w - w')/2 in
let h = h' in
let w = w' in
(* print_endline ((string_of_int h) ^ " " ^(string_of_int w)); *)
for y = 0 to (hh - 1) do
for x = 0 to (hw - 1) do
let y' = yoff + y * (h - 1) / (hh - 1) in
let x' = xoff + x * (w - 1) / (hw - 1)in
let dx = hget bmp x y in
arradd x' y' dx;
done
done
in
let _ = if (aspect = 1.0) then
f h w
else if (aspect < 1.0) then
f yh w
else
f h xw
in
(* now normalize again *)
for y = 0 to (h - 1) do
for x = 0 to (w - 1) do
let (v,c) = arrget x y in
if (c > 0) then
outset x y (v /. (float_of_int c))
done;
done;
Array.to_list outarr
;;
let get_columns n l =
let arr = Array.create n 0. in
Abez.iteri (fun i x ->
arr.(i mod n) <- arr.(i mod n) +. x
) l;
Array.to_list arr
;;
let buffer_to_linear bmp =
let (w,h) = b_w_h bmp in
let arr = Array.create (w * h) 0. in
for y = 0 to (h-1) do
for x = 0 to (w-1) do
arr.(x + y * w) <- hget bmp x y
done
done;
arr
;;
let run_fft_on lin_arr n st en =
let imag = Array.create n 0. in
let real = Array.create n 0. in
let imago = Array.create n 0. in
let realo = Array.create n 0. in
for i = st to en do
real.(i - st) <- lin_arr.(i);
done;
fft#fft_f real imag realo imago;
(realo,imago)
;;
let get_fft min' max' w h samples =
let lin_arr = Array.of_list samples in
let run_fft_on = run_fft_on lin_arr in
let arrl = h * w in
let rec find_next_two n s =
if (s >= n) then s else (find_next_two n (s*2))
in
let max2 = find_next_two (min arrl max') 1 in
let rec powers_of_two = function
n when n >= min' -> n :: (powers_of_two (n/2))
| _ -> []
in
let pwrs = powers_of_two max2 in
let lists = List.flatten (
List.map (
fun m ->
let max = arrl / m in
List.flatten (
Abez.for_map (
fun i ->
let start = m * i in
let ending = start + m - 1 in
let ending = min (arrl-1) ending in
let (r,i) = run_fft_on m start ending in
Array.to_list r
) max
)
) pwrs ) in
lists
;;
let get_avg_fft max2 h w samples =
let lin_arr = Array.of_list samples in
let run_fft_on = run_fft_on lin_arr in
let arrl = h * w in
let avg = Array.create max2 0. in
let max = arrl / max2 in
Abez.fori (
fun i ->
let start = max2 * i in
let ending = start + max2 - 1 in
let ending = min (arrl-1) ending in
let (r,i) = run_fft_on max2 start ending in
Abez.add_array avg r;
) max;
Array.to_list avg
;;