cocoa-xu / evision

Evision: An OpenCV-Erlang/Elixir binding
https://evision.app
Apache License 2.0
323 stars 22 forks source link

An error occurs when executing the warpAffine function #174

Closed RyoWakabayashi closed 1 year ago

RyoWakabayashi commented 1 year ago

warpAffine does'nt work in Evision 0.1.27 It works in Evision 0.1.25

affine =
  Nx.tensor(
    [
      [1, 0, 100],
      [0, 1, 50]
    ],
    type: :f32
  )

Evision.warpAffine(img, affine, {512, 512})
** (ArgumentError) argument error
    (evision 0.1.27) :evision_nif.warpAffine([src: #Reference<0.2800198295.3224764434.181611>, m: #Reference<0.2800198295.3224764428.181460>, dsize: {512, 512}])
    (evision 0.1.27) lib/generated/evision.ex:37259: Evision.warpAffine/3
    (stdlib 3.17.2) erl_eval.erl:685: :erl_eval.do_apply/6
    (elixir 1.14.2) lib/module/parallel_checker.ex:107: Module.ParallelChecker.verify/1

Evision 0.1.27

warpAffine_error

Evision 0.1.25

warpAffine_before

I run livebook on Docker

https://hub.docker.com/layers/livebook/livebook/0.8.1/images/sha256-ade30a713e59f32cdb2d074a3b8e70a533206777a68bd2021f0152ace69926d7?context=explore

cocoa-xu commented 1 year ago

Hi @RyoWakabayashi, thanks for reporting this issue!

TL; DR

This should be fixed in #175.

Details

After some investigation, I found that these commits caused this:

cfba80bbd591a59da72632d466d96fa799c209dc - OpenCV set defval to "" when defval == f"{a.tp}()", cfba80bb#R704-R706 a7e81732fc6893064da7a2229a1f2bf0dc0baa83 - where we changed to check the defval passed to crepr; this would set ArgInfo.has_default to false 77f35f8c97d68aa068fcc5fd6af0603c9b1aff22 - where we only return true if either ArgInfo.has_default or ArgInfo.outputarg is true.

In this issue, the optional keyword argument borderValue is nil, and the generated ArgInfo.has_default value for it was false, so evision_to_safe returned a false; therefore, not all preconditions were satisfied, so it returned an ArgumentError

{
    Mat src;
    Mat dst;
    Mat M;
    Size dsize;
    int flags=INTER_LINEAR;
    int borderMode=BORDER_CONSTANT;
    Scalar borderValue;

    // ArgInfo(name, outputarg, has_default)
    if( num_kw_args >= 3 && 
        evision_to_safe(env, evision_get_kw(env, erl_terms, "src"), src, ArgInfo("src", 0, 0)) && 
        evision_to_safe(env, evision_get_kw(env, erl_terms, "dst"), dst, ArgInfo("dst", 1, 0)) && 
        evision_to_safe(env, evision_get_kw(env, erl_terms, "m"), M, ArgInfo("M", 0, 0)) && 
        evision_to_safe(env, evision_get_kw(env, erl_terms, "dsize"), dsize, ArgInfo("dsize", 0, 0)) && 
        evision_to_safe(env, evision_get_kw(env, erl_terms, "flags"), flags, ArgInfo("flags", 0, 1)) && 
        evision_to_safe(env, evision_get_kw(env, erl_terms, "borderMode"), borderMode, ArgInfo("borderMode", 0, 1)) && 
        evision_to_safe(env, evision_get_kw(env, erl_terms, "borderValue"), borderValue, ArgInfo("borderValue", 0, 0)) )
    {
         ...
RyoWakabayashi commented 1 year ago

Thank you!