mirror of
https://github.com/opencv/opencv_contrib.git
synced 2025-10-16 22:35:51 +08:00

[GSoC] Julia - phase 2 * Use 64bit types by default for int and float * Type promotion julia * Fix DNN test * Remote whitespace
245 lines
9.4 KiB
Python
Executable File
245 lines
9.4 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
# This file is part of OpenCV project.
|
|
# It is subject to the license terms in the LICENSE file found in the top-level directory
|
|
# of this distribution and at http://opencv.org/license.html
|
|
# Copyright (C) 2020 by Archit Rungta
|
|
|
|
from __future__ import unicode_literals # Needed for python2
|
|
|
|
import hdr_parser, sys, re, os
|
|
from string import Template
|
|
from pprint import pprint
|
|
from collections import namedtuple
|
|
if sys.version_info[0] >= 3:
|
|
from io import StringIO
|
|
else:
|
|
from cStringIO import StringIO
|
|
import os, shutil
|
|
|
|
from parse_tree import *
|
|
|
|
|
|
jl_cpp_argmap = {}
|
|
jl_cpp_defmap = {}
|
|
julia_types = ["Int32", "Float32", "Float64", "Bool", "String", "Array", "Any"]
|
|
cv_types = ["UMat","Size" ]
|
|
|
|
submodule_template = Template('')
|
|
root_template = Template('')
|
|
with open("binding_templates_jl/template_cv2_submodule_cxx.jl", "r") as f:
|
|
submodule_template = Template(f.read())
|
|
with open("binding_templates_jl/template_cv2_root.jl", "r") as f:
|
|
root_template = Template(f.read())
|
|
with open("typemap.txt", 'r') as f:
|
|
tmp = f.readlines()
|
|
for ln in tmp:
|
|
ln = ln.strip('\n').split(':')
|
|
jl_cpp_argmap[ln[0]] = ln[1]
|
|
with open("defval.txt", 'r') as f:
|
|
tmp = f.readlines()
|
|
for ln in tmp:
|
|
ln = ln.strip('\n').split('|')
|
|
if ln[0] not in jl_cpp_defmap:
|
|
jl_cpp_defmap[ln[0]] = {}
|
|
jl_cpp_defmap[ln[0]][ln[1]] = ln[2]
|
|
|
|
|
|
def handle_def_arg(inp, tp = '', ns=''):
|
|
tp = tp.strip()
|
|
inp = inp.strip()
|
|
|
|
out = ''
|
|
|
|
if inp in jl_cpp_defmap[tp]:
|
|
out = jl_cpp_defmap[tp][inp]
|
|
elif inp != '':
|
|
print(inp+" not found")
|
|
# print(inp, tp, out)
|
|
return out
|
|
|
|
def handle_jl_arg(inp):
|
|
if not inp:
|
|
return ''
|
|
inp = inp.replace('std::', '')
|
|
if inp in jl_cpp_argmap:
|
|
return jl_cpp_argmap[inp]
|
|
inp = inp.replace('cv::', '')
|
|
return inp
|
|
# return outs
|
|
|
|
class ClassInfo(ClassInfo):
|
|
|
|
def get_jl_code(self):
|
|
|
|
if self.ismap:
|
|
return ''
|
|
return self.overload_get()+self.overload_set()
|
|
|
|
def overload_get(self):
|
|
stra = "function Base.getproperty(m::%s, s::Symbol)\n" %(self.mapped_name)
|
|
if self.isalgorithm:
|
|
stra = "function Base.getproperty(m::cv_Ptr{%s}, s::Symbol)\n" %(self.mapped_name)
|
|
for prop in self.props:
|
|
stra = stra + " if s==:" + prop.name+"\n"
|
|
stra = stra + " return cpp_to_julia(%s(m))\n"%self.get_prop_func_cpp("get", prop.name)
|
|
stra = stra + " end\n"
|
|
stra = stra + " return Base.getfield(m, s)\nend\n"
|
|
return stra
|
|
|
|
def overload_set(self):
|
|
|
|
stra = "function Base.setproperty!(m::%s, s::Symbol, v)\n" %(self.mapped_name)
|
|
if self.isalgorithm:
|
|
stra = "function Base.setproperty!(m::cv_Ptr{%s}, s::Symbol, v)\n" %(self.mapped_name)
|
|
|
|
for prop in self.props:
|
|
if not prop.readonly:
|
|
continue
|
|
stra = stra + " if s==:" + prop.name+"\n"
|
|
stra = stra + " %s(m, julia_to_cpp(v))\n"%(self.get_prop_func_cpp("set", prop.name))
|
|
stra = stra + " end\n"
|
|
stra = stra + " return Base.setfield!(m, s, v)\nend\n"
|
|
return stra
|
|
|
|
class FuncVariant(FuncVariant):
|
|
|
|
def promote_type(self, tp):
|
|
if tp=='int':
|
|
return 'long long'
|
|
elif tp =='float':
|
|
return 'double'
|
|
return tp
|
|
|
|
|
|
def get_argument_full(self, classname='', isalgo = False):
|
|
arglist = self.inlist + self.optlist
|
|
|
|
argnamelist = [arg.name+"::"+(handle_jl_arg(self.promote_type(arg.tp)) if handle_jl_arg(arg.tp) not in pass_by_val_types else handle_jl_arg(self.promote_type(arg.tp[:-1]))) for arg in arglist]
|
|
argstr = ", ".join(argnamelist)
|
|
return argstr
|
|
|
|
def get_argument_opt(self, ns=''):
|
|
# [print(arg.default_value,":",handle_def_arg(arg.default_value, handle_jl_arg(arg.tp))) for arg in self.optlist]
|
|
try:
|
|
str2 = ", ".join(["%s::%s = %s(%s)" % (arg.name, handle_jl_arg(self.promote_type(arg.tp)), handle_jl_arg(self.promote_type(arg.tp)) if (arg.tp == 'int' or arg.tp=='float' or arg.tp=='double') else '', handle_def_arg(arg.default_value, handle_jl_arg(self.promote_type(arg.tp)), ns)) for arg in self.optlist])
|
|
return str2
|
|
except KeyError:
|
|
return ''
|
|
|
|
def get_argument_def(self, classname, isalgo):
|
|
arglist = self.inlist
|
|
argnamelist = [arg.name+"::"+(handle_jl_arg(self.promote_type(arg.tp)) if handle_jl_arg(self.promote_type(arg.tp)) not in pass_by_val_types else handle_jl_arg(self.promote_type(arg.tp[:-1]))) for arg in arglist]
|
|
argstr = ", ".join(argnamelist)
|
|
return argstr
|
|
|
|
def get_return(self, classname=''):
|
|
argstr = ''
|
|
arglist = self.inlist + self.optlist
|
|
return "return cpp_to_julia(%s(%s))" %(self.get_wrapper_name(), ",".join(["julia_to_cpp(%s)" % (x.name) for x in arglist]))
|
|
|
|
def get_algo_tp(self, classname, isalgo):
|
|
if not isalgo or not classname:
|
|
return ''
|
|
return ' where {T <: %s}' % classname
|
|
|
|
def get_complete_code(self, classname='', isalgo = False, iscons = False, gen_default = True, ns = ''):
|
|
if classname and not iscons:
|
|
if isalgo:
|
|
self.inlist = [ArgInfo("cobj", "cv_Ptr{T}")] + self.inlist
|
|
else:
|
|
self.inlist = [ArgInfo("cobj", classname)] + self.inlist
|
|
map_name = self.mapped_name
|
|
if ns!='cv':
|
|
map_name = '%s_%s' %(ns.split('::')[-1], map_name)
|
|
outstr = 'function %s(%s)%s\n\t%s\nend\n' % (map_name, self.get_argument_full(classname, isalgo), self.get_algo_tp(classname, isalgo),self.get_return())
|
|
|
|
|
|
str2 = ", ".join([x.name for x in self.inlist + self.optlist])
|
|
# outstr = outstr +
|
|
if self.get_argument_opt() != '' and gen_default:
|
|
outstr = outstr + ('%s(%s; %s)%s = %s(%s)\n' % (map_name, self.get_argument_def(classname, isalgo), self.get_argument_opt(ns), self.get_algo_tp(classname, isalgo), map_name, str2))
|
|
|
|
if iscons and len(self.inlist+self.optlist)==0 and ns=='cv':
|
|
return ''
|
|
|
|
return outstr
|
|
|
|
|
|
|
|
def gen(srcfiles):
|
|
namespaces, _ = gen_tree(srcfiles)
|
|
|
|
jl_code = StringIO()
|
|
for name, ns in namespaces.items():
|
|
cv_types.extend(ns.registered)
|
|
jl_code = StringIO()
|
|
nsname = name
|
|
for e1,e2 in ns.enums.items():
|
|
# jl_code.write('\n const {0} = Int32'.format(e2[0]))
|
|
jl_code.write('\n const {0} = Int64 \n'.format(e2[0].replace("cv::", "").replace("::", "_")))
|
|
|
|
# Do not duplicate functions. This should prevent overwriting of Mat function by UMat functions
|
|
function_signatures = []
|
|
for cname, cl in ns.classes.items():
|
|
cl.__class__ = ClassInfo
|
|
jl_code.write(cl.get_jl_code())
|
|
for mname, fs in cl.methods.items():
|
|
for f in fs:
|
|
f.__class__ = FuncVariant
|
|
sign = (f.name, f.mapped_name, f.classname, [x.tp for x in f.inlist+f.optlist])
|
|
if sign in function_signatures:
|
|
print("Skipping entirely: ", f.name)
|
|
continue
|
|
sign2 = (f.name, f.mapped_name, f.classname, [x.tp for x in f.inlist])
|
|
gend = True
|
|
if sign2 in function_signatures:
|
|
print("Skipping default declaration: ", f.name)
|
|
gend = False
|
|
jl_code.write('\n%s' % f.get_complete_code(classname = cl.mapped_name, isalgo = cl.isalgorithm, gen_default = gend, ns=nsname))
|
|
function_signatures.append(sign)
|
|
function_signatures.append(sign2)
|
|
for f in cl.constructors:
|
|
f.__class__ = FuncVariant
|
|
jl_code.write('\n%s' % f.get_complete_code(classname = cl.mapped_name, isalgo = cl.isalgorithm, iscons = True, ns=nsname))
|
|
for mname, fs in ns.funcs.items():
|
|
for f in fs:
|
|
f.__class__ = FuncVariant
|
|
sign = (f.name, f.mapped_name, f.classname, [x.tp for x in f.inlist+f.optlist])
|
|
if sign in function_signatures:
|
|
print("Skipping entirely: ", f.name)
|
|
continue
|
|
gend = True
|
|
sign2 = (f.name, f.mapped_name, f.classname, [x.tp for x in f.inlist])
|
|
if sign2 in function_signatures:
|
|
print("Skipping default declaration: ", f.name)
|
|
gend = False
|
|
|
|
jl_code.write('\n%s' % f.get_complete_code(gen_default = gend, ns=nsname))
|
|
function_signatures.append(sign)
|
|
function_signatures.append(sign2)
|
|
|
|
|
|
imports = ''
|
|
for namex in namespaces:
|
|
if namex.startswith(name) and len(namex.split('::')) == 1 + len(name.split('::')):
|
|
imports = imports + '\ninclude("%s_cxx_wrap.jl")'%namex.replace('::', '_')
|
|
code = ''
|
|
if name == 'cv':
|
|
code = root_template.substitute(modname = name, code = jl_code.getvalue(), submodule_imports = imports)
|
|
else:
|
|
code = submodule_template.substitute(code = jl_code.getvalue(), submodule_imports = imports)
|
|
|
|
with open ('autogen_jl/%s_cxx_wrap.jl' % ns.name.replace('::', '_'), 'w') as fd:
|
|
fd.write(code)
|
|
|
|
|
|
|
|
|
|
|
|
srcfiles = hdr_parser.opencv_hdr_list
|
|
if len(sys.argv) > 1:
|
|
srcfiles = [l.strip() for l in sys.argv[1].split(';')]
|
|
|
|
gen(srcfiles)
|