diff --git a/scripts/run_experiments.jl b/scripts/run_experiments.jl index a1c117d9b713c8c5700d45ee007f41587f3265f5..02af05e6dd0632acf55ca4084e7c5c144d588106 100644 --- a/scripts/run_experiments.jl +++ b/scripts/run_experiments.jl @@ -1,5 +1,5 @@ using LinearAlgebra: I, det, dot, norm, normalize -using SparseArrays: sparse +using SparseArrays: sparse, ishermitian using Statistics: mean using Colors: Gray @@ -322,6 +322,8 @@ function step!(st::L1L2TVState) print("solve ... ") A = Au + Ap b = bu + bp + #println(norm(A - A')) + #println(ishermitian(A)) #A, b = assemble(st.du.space, du_a, du_l; # st.g, st.u, nablau = nabla(st.u), st.p1, st.p2, st.tdata) st.du.data .= A \ b @@ -806,7 +808,7 @@ function denoise(ctx) project_image! = project_l2_lagrange! eps_newton = 1e-5 # cauchy criterion for inner newton loop - n_refine = 6 + n_refine = 5 # convert to cartesian coordinates g_arr = from_img(ctx.params.g_arr) @@ -891,7 +893,7 @@ function experiment_denoise(ctx) df = DataFrame() denoise(Util.Context(ctx; name = "test", df, g_arr, mesh, - alpha1 = 0., alpha2 = 30., lambda = 1., beta = 1e-5, + alpha1 = 0., alpha2 = 50., lambda = 1., beta = 1e-5, gamma1 = 1e-4, gamma2 = 1e-4, eps_newton = 1e-5, adaptive = true, )) @@ -1246,46 +1248,119 @@ function experiment_approximation(ctx) )) end -function inpaint(img, imgmask; params...) - size(img) == size(imgmask) || - throw(ArgumentError("non-matching dimensions")) +# TODO: deduplicate, cf. optflow() +function inpaint(ctx) + # expect ctx.params.g_arr - m = 1 - img = from_img(img) # coord flip - imgmask = from_img(imgmask) # coord flip - mesh = init_grid(img; type=:vertex) + project_image! = project_qi_lagrange! + n_refine = 5 + + # convert to cartesian coordinates + g_arr = from_img(ctx.params.g_arr) + mask_arr = from_img(ctx.params.mask_arr) + + mesh = init_grid(g_arr, floor.(Int, size(g_arr) ./ 2^(n_refine / 2))...) + mesh_area = area(mesh) # inpaint specific stuff Vg = FeSpace(mesh, P1(), (1,)) - mask = FeFunction(Vg, name = "mask") + _mask = FeFunction(Vg, name = "mask") - T(tdata, u) = isone(tdata[begin]) ? u : zero(u) + T(tdata, u) = abs(tdata[begin] - 1.) < 1e-8 ? u : zero(u) + T(::typeof(adjoint), tdata, v) = T(tdata, v) S(u, nablau) = u - st = L1L2TVState{m}(mesh; T, tdata = mask, S, params...) - - # FIXME: currently dual grid only - interpolate!(mask, x -> imgmask[round.(Int, x)...]) - #interpolate!(mask, x -> abs(x[2] - 0.5) > 0.1) - interpolate!(st.g, x -> imgmask[round.(Int, x)...] ? img[round.(Int, x)...] : 0.) - m = (size(img) .- 1) ./ 2 .+ 1 - interpolate!(st.g, x -> norm(x .- m) < norm(m) / 3) - - save_inpaint(i) = - output(st, "output/$(st.name)_$(lpad(i, 5, '0')).vtu", - st.g, st.u, st.p1, st.p2, st.est, mask) - - pvd = paraview_collection("output/$(st.name).pvd") - pvd[0] = save_inpaint(0) - for i in 1:3 - step!(st) - estimate_pd!(st) - pvd[i] = save_inpaint(i) - println() + st = L1L2TVState{1}(mesh; + T, tdata = _mask, S, + ctx.params.alpha1, ctx.params.alpha2, + ctx.params.lambda, ctx.params.beta, + ctx.params.gamma1, ctx.params.gamma2) + + function interpolate_image_data!() + println("interpolate image data ...") + project_image!(st.g, g_arr) + project_image!(st.tdata, mask_arr) + end + + save_step(i) = + output(st, joinpath(ctx.outdir, "output_$(lpad(i, 5, '0')).vtu"), + st.g, st.u, st.p1, st.p2, st.est) + + pvd = paraview_collection(joinpath(ctx.outdir, "output.pvd")) do pvd + + interpolate_image_data!() + pvd[0] = save_step(0) + + i = 0 + k_newton = 0 + k_refine = 0 + while true + # interior newton + k_newton += 1 + step!(st) + norm_step_ = norm_step(st) / sqrt(mesh_area) + println("norm_step = $norm_step_") + + # interior newton stop criterion + norm_step_ > ctx.params.eps_newton && k_newton < 30 && continue + k_newton = 0 + + # plot + i += 1 + display(plot(grayclamp.(to_img(sample(st.u))))) + estimate_res!(st) + pvd[i] = save_step(i) + #break + + # refinement stop criterion + k_refine += 1 + k_refine > n_refine && break + println("refine ...") + #estimate_res!(st) + marked_cells = Set(mark(st; theta = 0.5)) + # manually mark all cell within inpainting domain, since the + # estimator is not reliable there + for cell in cells(mesh) + bind!(st.tdata, cell) + maskv = evaluate(st.tdata, SA[1/3, 1/3]) + if abs(maskv[begin] - 1.) > 1e-8 + push!(marked_cells, cell) + end + end + #marked_cells = Set(axes(mesh.cells, 2)) + mesh, fs = refine(mesh, marked_cells; + st.est, st.g, st.u, st.p1, st.p2, st.du, st.dp1, st.dp2, st.tdata) + st = L1L2TVState(st; mesh, fs.tdata, + fs.est, fs.g, fs.u, fs.p1, fs.p2, fs.du, fs.dp1, fs.dp2) + interpolate_image_data!() + end end + #CSV.write(joinpath(ctx.outdir, "energies.csv"), df) + + u_sampled = sample(st.u) + saveimg(joinpath(ctx.outdir, "g.png"), to_img(g_arr)) + saveimg(joinpath(ctx.outdir, "output.png"), grayclamp.(to_img(u_sampled))) + savedata(joinpath(ctx.outdir, "data.tex"); + ctx.params.eps_newton, n_refine, + st.alpha1, st.alpha2, st.lambda, st.beta, st.gamma1, st.gamma2, + width=size(u_sampled, 1), height=size(u_sampled, 2)) return st end +function experiment_inpaint(ctx) + g_arr = loadimg(joinpath(ctx.indir, "input.png")) + mask_arr = loadimg(joinpath(ctx.indir, "mask.png")) + mesh = init_grid(g_arr;) + + df = DataFrame() + inpaint(Util.Context(ctx; name = "test", df, + g_arr, mask_arr, mesh, + alpha1 = 0., alpha2 = 50., lambda = 1., beta = 1e-5, + gamma1 = 1e-4, gamma2 = 1e-4, + eps_newton = 1e-4, adaptive = true, + )) +end + function optflow(ctx) size(ctx.params.imgf0) == size(ctx.params.imgf1) || throw(ArgumentError("non-matching image sizes"))