Created
June 18, 2011 05:56
-
-
Save ultraist/1032841 to your computer and use it in GitHub Desktop.
opencv-haar-classifer XML translater
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
sum = 0.0; | |
<% node[:feature][:rects].each do |rect| %> | |
xs = x + Math.round(<%= rect[0] %> * scale); | |
ys = y + Math.round(<%= rect[1] %> * scale); | |
w = Math.round(<%= rect[2] %> * scale); | |
h = Math.round(<%= rect[3] %> * scale); | |
<% if (node[:feature][:tilted]) %> | |
sum += sumtf(integral_tilted, xs, ys, w, h) * <%= rect[4] %> * s2h_inv; | |
<% else %>; | |
sum += sumf(integral, xs, ys, w, h) * <%= rect[4] %> * s2_inv; | |
<% end %> | |
<% end %> | |
if (sum < <%= sprintf("%E", node[:threshold]) %> * variance_norm_factor ) { | |
<% if node[:left_val] %> | |
p += <%= sprintf("%E", node[:left_val]) %>; | |
<% else %> | |
<%= tree_exec(c, nodes, nodes[node[:left_node]])%> | |
<% end %> | |
} else { | |
<% if node[:right_val] %> | |
p += <%= sprintf("%E", node[:right_val]) %>; | |
<% else %> | |
<%= tree_exec(c, nodes, nodes[node[:right_node]])%> | |
<% end %> | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# haargen.rb -l javascript -i haarcascade_frontalface_alt.xml > frontalface_alt.js | |
require 'rubygems' | |
require 'rexml/document' | |
require 'optparse' | |
require 'json' | |
require 'erb' | |
$lang = "javascript" | |
def parse_rect(node) | |
rect = node.text.strip.split(/\s+/) | |
(0 ... 4).each do |i| | |
rect[i] = rect[i].to_i | |
end | |
rect[4] = rect[4].to_f | |
rect | |
end | |
def parse_tree_node(node) | |
tree_node = {} | |
tree_node[:threshold] = node.elements["threshold"].text.to_f | |
if (node.elements["left_val"]) | |
tree_node[:left_val] = node.elements["left_val"].text.to_f | |
elsif (node.elements["left_node"]) | |
tree_node[:left_node] = node.elements["left_node"].text.to_i | |
end | |
if (node.elements["right_val"]) | |
tree_node[:right_val] = node.elements["right_val"].text.to_f | |
elsif (node.elements["right_node"]) | |
tree_node[:right_node] = node.elements["right_node"].text.to_i | |
end | |
tree_node[:feature] = {} | |
tree_node[:feature][:rects] = [] | |
node.elements.each("feature/rects/_") do |rect| | |
tree_node[:feature][:rects] << parse_rect(rect) | |
end | |
tree_node[:feature][:tilted] = node.elements["feature/tilted"].text.to_i == 1 ? true : false; | |
tree_node | |
end | |
def parse_tree(node) | |
tree = [] | |
node.elements.each("_") do |child| | |
tree << parse_tree_node(child) | |
end | |
tree | |
end | |
def parse_stages(node) | |
stage = {} | |
stage[:threshold] = node.elements["stage_threshold"].text.to_f | |
stage[:parent] = node.elements["parent"].text.to_i | |
stage[:next] = node.elements["next"].text.to_i | |
stage[:trees] = [] | |
node.elements.each("trees/_") do |tree| | |
stage[:trees] << parse_tree(tree) | |
end | |
stage | |
end | |
def parse_opencv_haar_classifier(filename) | |
classifier = {} | |
file = File.new(filename) | |
doc = REXML::Document.new file | |
classifier[:size] = doc.elements["opencv_storage/*/size"].text.split(' ').map{|v| v.to_i} | |
classifier[:name] = doc.elements["opencv_storage/*"].name | |
classifier[:stages] = [] | |
doc.elements.each("opencv_storage/*/stages/_") do |stage| | |
classifier[:stages] << parse_stages(stage) | |
end | |
classifier | |
end | |
def exec_erb(filename, outer_binding) | |
erb = ERB.new(File.read(filename)) | |
erb.filename = filename | |
erb.result(outer_binding) | |
end | |
def tree_exec(c, nodes, node) | |
exec_erb(File.join($lang, "_tree.erb"), binding) | |
end | |
def u(x) | |
x < 0 ? 2 ** 32 : x; | |
end | |
def fix(c) | |
scale = 1.0 | |
width = (c[:size][0] - 2) * scale | |
height = (c[:size][1] - 2) * scale | |
weight_scale = 1.0 / (width * height); | |
c[:extend] = false | |
c[:stages].each do |stage| | |
stage[:trees].each do |tree| | |
tree.each do |node| | |
rects = node[:feature][:rects] | |
sum0 = 0.0 | |
area0 = 0.0 | |
rects.each_index do |k| | |
tr = {}; | |
tr[:x] = (rects[k][0] * scale).round | |
tr[:width] = (rects[k][2] * scale).round | |
tr[:y] = (rects[k][1] * scale).round | |
tr[:height] = (rects[k][3] * scale).round | |
correction_ratio = weight_scale | |
if (node[:feature][:tilted]) | |
correction_ratio *= 0.5 | |
c[:extend] = true | |
end | |
rects[k][4] = rects[k][4] * correction_ratio; | |
if( k == 0 ) | |
area0 = tr[:width] * tr[:height] | |
else | |
sum0 += rects[k][4] * tr[:width] * tr[:height] | |
end | |
end | |
rects[0][4] = -sum0.to_f / area0.to_f | |
end | |
end | |
end | |
end | |
def main | |
file = nil | |
opt = OptionParser.new | |
opt.on('-l LANGUAGE', ["javascript", "glsl"]) do |l| | |
if (l) | |
$lang = l | |
end | |
end | |
opt.on('-i XML') do |d| | |
file = d | |
end | |
argv = opt.parse(ARGV) | |
unless (file) | |
warn opt.to_s | |
exit | |
end | |
c = parse_opencv_haar_classifier(file) | |
fix(c) | |
puts exec_erb(File.join($lang, "main.erb"), binding) | |
end | |
main |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var nvjs = nvjs || {}; | |
nvjs.ext = nvjs.ext || {}; | |
nvjs.ext.haar_classifier = nvjs.ext.haar_classifier || {}; | |
nvjs.ext.haar_classifier["<%= c[:name] %>"] = nvjs.ext.haar_classifier["<%= c[:name] %>"] || {}; | |
nvjs.ext.haar_classifier["<%= c[:name] %>"].size = <%= "{width:#{c[:size][0]}, height:#{c[:size][1]}}" %>; | |
nvjs.ext.haar_classifier["<%= c[:name] %>"].extend = <%= c[:extend] %>; | |
nvjs.ext.haar_classifier["<%= c[:name] %>"].predict = | |
function(integral, integral_tilted, x, y, | |
scale, variance_norm_factor) | |
{ | |
var sumf = function(integral, x, y, w, h) { | |
return nvjs.ip.integral_v(integral, x, y, x + w, y + h); | |
}; | |
var sumtf = function(t, x, y, w, h) { | |
return (t.v[(y * t.cols) + x] | |
- t.v[((y + h) * t.cols) + (x - h)] | |
- t.v[((y + w) * t.cols) + (x + w)] | |
+ t.v[((y + w + h) * t.cols) + (x + w - h)]); | |
}; | |
var ys, xs, w, h; | |
var sum, p; | |
var s2_inv = 1.0 / (scale * scale); | |
var s2h_inv = 1.0 / (scale * scale * 0.5); | |
<% c[:stages].each do |stage| %>; | |
p = 0.0; | |
<% stage[:trees].each do |tree| %>; | |
<%= tree_exec(c, tree, tree[0]) %> | |
<% end %> | |
if (p < <%= sprintf("%E", stage[:threshold]) %>) { | |
return false; | |
} | |
<% end %> | |
return true; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment