
    #}j*                        d Z ddlmZ ddlZddlZddlZddlmZ ddlZ	ddl
mZ ddlZddZddZdd		 	 	 	 	 	 	 	 	 	 	 dd
Z	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 	 	 ddZddZedk(  r e        yy)a  Patch-based robust quadratic surface denoising with a strict trust region.

Each original vertex is projected only along its original normal onto a robust
local quadratic surface fitted to nearby original samples.  Connectivity never
changes.  This removes coherent scan/generative ripples that one-ring filters
cannot see while retaining local curvature better than plane projection.
    )annotationsN)Path)cKDTreec                     t        j                         } | j                  dd       | j                  dd       | j                         S )Nz--inputT)requiredz--outdir)argparseArgumentParseradd_argument
parse_args)parsers    ..runtime/model-denoise-research/mls_denoise.pyr   r      sE    $$&F
	D1

T2    c                   t        j                  |       }t        j                  | d d df         dk  }d||df<   d|| df<   t        j                  t        j
                  ||             j                  t         j                        }t        j                  t        j
                  | |            j                  t         j                        }||fS )N   g)\(?      ?r   )np
zeros_likeabsdmnormalize_rowscrossastypefloat32)normals
referencesuse_z	tangent_x	tangent_ys        r   tangent_framesr      s    w'JFF71a4=!D(EJuaxJvqy!!"((:w"?@GG

SI!!"((7I">?FFrzzRIir   i   )
batch_sizec               	   !" t        |       }t        j                  |t        j                        }t	        |      \  }}g }	d!t        d||      D ]  }
t        |
|z   |      }| |
| }|j                  ||d      \  }}t        j                  |t        j                        }t        j                  |t        j                        }| |   |d d d d d f   z
  }||
| }||
| }||
| }t        j                  |d d df   t        j                  d            }|	j                  |d d t        dt        |      dz           j                                t        j                  d||      |d d d f   z  }t        j                  d||      |d d d f   z  }t        j                  d||      "t        j                  t        j                   |      ||||z  ||z  ||z  fd	
       t        j"                  dt        j$                  ||d d d f   z        z        j'                  t        j                        }t        j                  d||   |      }t        j(                  t        j                  dddt        j*                  |dd      z  z
              }t        j"                  dt        j$                  |dz        z        j'                  t        j                        }||z  }t        j                  |d d df   d      |d d df<   d !"fd} ||      }"t        j                  d |      z
  }t        j                  t        j,                  t        j.                  |      d
      t        j                  d      z  |t        j                  d      z        }t        j$                  t        j*                  dt        j$                  |d|d d d f   z  z        z
  dd            } |||j'                  t        j                        z        }|d d df   j'                  t        j                        ||
|  |t1        t        j,                  |	            t1        t        j2                  |	d            !dfS )Ndtyper   )kworkersg:0yE>      z
bki,bi->bkr   axisg               g       @g      r   g      gRQ?c                   t        j                  d| d      }t        j                  d| d      }t        j                  |dd      }t        j                  |dz  d	      j	                  t         j
                        }|d d t        d
      t        d
      fxx   |d d d f   z  cc<   |d d ddfxx   |t        j
                  d      z  z  cc<   	 t         j                  j                  ||      S # t         j                  j                  $ rA t        |      z  t        j                  t        |      d
ft         j
                        cY S w xY w)Nzbki,bk,bkj->bijT)optimizezbki,bk,bk->bir'   r   )axis1axis2gHz>g|=   r   g+?r"   )r   einsumtracemaximumr   r   rangelinalgsolveLinAlgErrorlenzeros)weightmatrixrhsr2   regularizerAcondition_failureszs        r   r6   z'robust_quadratic_offsets.<locals>.solveQ   s   YY0!VQNF))OQDICHHV1A6E**UT\59@@LK1eAha()[D-AA) 1a7O{RZZ->>>ODyyvs3399(( D"c&k1"xxVa 0

CCDs   C8 8AEEg)Ǻ?g-C6*?g=
ףp@ffffff?)patch_radius_medianpatch_radius_p95r?   )r:   
np.ndarrayreturnrD   )r8   r   r9   r   r   r4   minqueryasarrayint32r3   extendmaxtolistr1   stack	ones_likeexpsquarer   sqrtclipmedianr   floatquantile)#verticesr   treeneighbor_countr    countoffsetsr   r   radius_samplesstartendcentersdistanceneighbordeltanxnynnpatch_radiusxyspatial
normal_dotnormal_distancenormal_weightweightsr6   coefficientsresidualscalerobustr>   r?   r@   s#                                   @@@r   robust_quadratic_offsetsrq   (   s    MEhhuBJJ/G)'2Iy"$Nq%, 3C%*$e,5%!ZZ>2ZN(::hbjj9::hbhh7"WQaZ%88uS!uS!U3zz(1b5/2::d3CDl+Mc!S5F"5L.M+MNUUWXIIlE2.ag1FFIIlE2.ag1FFIIlE2.HHbll1oq!QUAE1q5AJ&&		(\!T'5J*J KKLSSTVT^T^_YY|WX->C
''JJsC#
D#(F"FFG
 tbii$0F&GGHOOPRPZPZ[M)

71a4=#61	D  W~ryyq,??

IIbffX&Q/"**V2DD2::d++
 27738uuQPTW~?U3V)W#WY\^abcWv}}RZZ'@@A)!Q$/66rzzBcg3Cj $RYY~%>?!"++nd"CD0  r   c                    t        j                  | t         j                        }t        d      D ]A  }|t        j                  |d d |f   ||       j                  t         j                        z  }C |dz  S )Nr"      )rl   	minlengthg      @)r   r9   r   r4   bincountr   )vertex_countfaces
face_areasresultcorners        r   vertex_area_weightsr{   r   sj     XXl"**5F( "++!V)jL

&
	 C<r   c                   |j                         }t        j                  t        |      t              }t        d      D ]  }t        j                  ||d      \  }}}t        j                  d||      }	|	dk  |dk  z  }
t        j                  |
      s n5t        j                  ||
   j                               }d||<   | |   ||<    |t        |j                               fS )	Nr"      Fneed_centroidszij,ij->ir+   g-q=T)copyr   r9   r8   boolr4   r   face_geometryr1   anyuniqueravelintsum)original_vertices	candidaterw   original_face_normalsrV   reverted_r   areas	alignmentbadbad_verticess               r   revert_flipped_facesr   }   s     ~~HxxHT2H1X A,,XuUSIIj*?I	CEEM2vvc{yys!1!1!34!%!2<!@A S(((r   c                h    t        j                  | |d      \  }}}t        j                  |||      S )NFr~   )r   r   reflection_rms)rV   rw   adjacent_facessmooth_maskr   r   s         r   reflection_metricr      s3     $$XuUKMGQWnkBBr   c                 
   t               } t        | j                        j                         }t        | j                        j                         }|j                  dd       t        j                  |      }t        j                  |d   t        j                        }t        j                  |d   t        j                        }t        t        j                  j                  |j                  d      |j                  d      z
              }t!        j"                  |t%        |            }|d   }|d	   }	|d
   }
t!        j&                  ||      \  }}}t!        j(                  ||||      }t!        j*                  |||ddd      }t!        j,                  |||	|
t%        |            \  }}|dk  }t/        |      }t1        t%        |      ||      }t        |j3                  t        j4                              }t7        t!        j8                  ||            }t!        j:                  ||d         }t!        j<                  ||||||||||
      }ddddddddddddd}t?        |      t%        |      t%        |      |d   |i d}tA        jB                         }|jE                         D ]T  \  }}tG        d| d|d     d!       tI        ||||d          \  }}|t        j                  |d"         dd#|z  z
  z  z  }t        t        j2                  ||z        t        jJ                  |j3                         d$      z        } |t        j                  |       d|z
  z  z  }t        j                  ||d%   z        }!t        jL                  ||! |!      }|||d d d f   z  z   }"tO        ||"||      \  }"}#|| d&z  }$t        jP                  |$|"jS                  t        j                        |'       t!        j<                  ||"||||||||
      }%t        d(d|%d)   |d)   z  z
  z        |%d*<   t        d(d|%d+   |d+   z  z
  z        |%d,<   |t?        |$      |t        |jU                               t        t        jV                  t        jT                  ||z                    t        t        jX                  t        j6                  |      d            |#|%d-|d.   |<   tG        d| d/|%d,   d0d1|%d2   d3d4|%d5           W tA        jB                         |z
  |d6<   |d7z  j[                  t]        j^                  |d89      d:;       tG        d<|d6   d=d>       y )?NT)parentsexist_okrV   r"   rw   r   r)   r   adjacent_edgesboundary_vertices   g(\?g=
ףp=?)blendg)\(?unique_edges0   g333333?g~jtX?)	neighborsgainmax_pct`   rA   g~jth?   r   g{Gzt?)zpatch-smallzpatch-balancedz
patch-widestats)inputrV   	trianglestopologybaselinevariants[z] robust quadratic patches (r   z neighbors)r   g
ףp=
?g#B;r   z.npz)rV   rw   g      Y@smooth_region_normal_tv_rmsnormal_tv_improvement_pctreflection_field_rmsreflection_improvement_pct)configoutputpatchraw_offset_meanraw_offset_rmsraw_offset_p95_abs!reverted_vertices_for_flip_safetymetricsr   z] reflection z.2fz% better, p95 displacement_p95z.7fz, flips flipped_faceselapsed_secondszpatch-metrics.jsonr   )indentzutf-8)encodingzDone in z.1fs)0r   r   r   resolveoutdirmkdirr   loadrH   r   rI   rT   r5   normrK   rF   r   build_topologyr8   r   vertex_normalsdiffuse_normalsfeature_protectionr   r{   r   float64r   signed_volumemean_edge_lengthgeometry_metricsstrtimeperf_counteritemsprintrq   r3   rR   r   savezr   meanrQ   rU   
write_textjsondumps)&argssourcer   datar   rw   diagonalr   r   r   r   r   rx   r   original_vertex_normalsguidancefeature_strengthguide_distancer   rW   vertex_areaoriginal_areaoriginal_volume	mean_edger   r   reportstartednamer   rZ   patch_statsmean_offsettrustr   reverted_verticesr   r   s&                                         r   mainr      s   <D$**%%'F$++&&(F
LLL-776?D

4
#32::FJJtG}BHH5E
		(,,!,47H7L7LRS7L7TTUH   ,=(>?H./N./N !45+-+;+;<Mu+U(:q //5*.C !!z>2t4H (*'<'<($n !4'K$%D%c*;&<eZPK*..rzz.:;M"**+<eDEO##$5x7OPI""H &(&I(*DVL$'&IH V)*ZW%!F !G ( 0
f$3F;4G3HTU76f[>Q 
 	2::fVn-t>N7N1NOOBFF7[#89BJJ{GXZ_<``a2::k*c4D.DEE

8fY&778'''E651%(?'!T'BR(RR	';y%1F(
$	$ TF$-'
)"2"22::">eL%%!
 05S7#@AHMjDkkkl0
+, 16S7#9:XF\=]]]^1
,- &k $W\\^4#BGGBGGGg4E,F$GH"'BFF7OT(J"K1B	$
z4  	v]7+G#H"M N-.s38GO<T;UW	
[0
b !% 1 1 3g =F""..

6!$w /  
HV-.s31
56r   __main__)rE   zargparse.Namespace)r   rD   rE   ztuple[np.ndarray, np.ndarray])rV   rD   r   rD   rW   r   rX   r   r    r   rE   z#tuple[np.ndarray, dict[str, float]])rv   r   rw   rD   rx   rD   rE   rD   )
r   rD   r   rD   rw   rD   r   rD   rE   ztuple[np.ndarray, int])
rV   rD   rw   rD   r   rD   r   rD   rE   rT   )rE   None)__doc__
__future__r   r   r   r   pathlibr   numpyr   scipy.spatialr   denoise_meshr   r   r   rq   r{   r   r   r   __name__ r   r   <module>r      s$   #      !    GGG G 	G G )GT(6@)!)) ) &	)
 )(CCC C 	C
 Cs7l zF r   