o
    @Tj                     @   s\   d Z ddlZddlZddlmZ ddlmZmZ ddlm	Z	 e
eZdZG dd dZdS )	z2Background removal service using rembg + BiRefNet.    N)Image)new_sessionremove)settingsi   c                   @   s~   e Zd ZdZdd Z	ddededefdd	Ze	
		dde	j	de
de
de
de	j	f
ddZeefdededefddZdS )SegmentationServicez=Stateless background removal using rembg with BiRefNet model.c              
   C   s*  dd l }t|dr(z|  W n ty' } ztd| W Y d }~nd }~ww tj}| }t	d|
 | dd tjdD pDd }t	d||pLd	 |d urZt||d
| _nt|d| _| jj }t	d| |r|d t| |krtd|| d S d|v rd|vrtd| d S d S d S )Nr   preload_dllszort.preload_dlls() failed: %sz"onnxruntime device=%s available=%sc                 S   s   g | ]
}|  r|  qS  )strip).0pr   r   A/home/ubuntu/htdocs/ootd-api/app/services/segmentation_service.py
<listcomp>$   s    z0SegmentationService.__init__.<locals>.<listcomp>,z1Loading rembg session (model=%s, providers=%s)...auto)
model_name	providers)r   z!rembg session active providers=%suP   Requested providers %s but session uses %s — CUDA libs may have failed to loadCUDAExecutionProviderz>CUDAExecutionProvider is available but session fell back to %s)onnxruntimehasattrr   	Exceptionloggerwarningr   SEGMENTATION_MODELget_available_providersinfo
get_deviceSEGMENTATION_PROVIDERSsplitr   _sessioninner_sessionget_providerslen)selfortemodel	available	requestedactiver   r   r   __init__   sP   


zSegmentationService.__init__Fimage_bytescenter_cropreturnc                 C   s`   |  |}t|| jdd}|r.tt|d}| |}t }|j	|dd |
 }|S )a>  Remove background from image bytes.

        Args:
            image_bytes: Raw image bytes (JPEG, PNG, WebP, etc.)
            center_crop: If True, crop to 9:16 with person centered and
                         minimal top/bottom margins.

        Returns:
            PNG bytes with transparent background.
        T)datasessionpost_process_maskRGBAPNGformat)_resize_for_segmentationr   r   r   openioBytesIOconvert_center_crop_personsavegetvalue)r"   r*   r+   resizedresultimgbufr   r   r   remove_backgroundB   s   

z%SegmentationService.remove_background皙?        {Gz?r>   pad_top_ratiopad_bottom_ratiopad_horizontal_ratioc                  C   s  |  d}| }|du rtd | S |\}}}}	|| }
|	| }|
t|
| d  }|t||  t||  }t|d d }||krK|}|}n
|}t|d d }|| d }||	 d }t|||  d }||d  | }|| }||d  }|| }td||fd}td	|}t| j	|}td	|}t| j
|}||ks||kr|S | ||||f}|| }|| }||||f |S )
u  Crop RGBA image to 9:16 with person centered, minimal margins.

        Detects the person region from the alpha channel bounding box,
        adds asymmetric vertical padding (top 5%, bottom 10%) and
        horizontal padding (5%), then fits to 9:16 aspect ratio.
        The person is never cropped — if the person is wider than 9:16
        allows, the frame expands vertically to maintain the ratio.
        Areas outside the original image are filled with transparency.
        ANz=center_crop: no non-transparent pixels found, returning as-is   	      r0   )r   r   r   r   r   )
getchannelgetbboxr   r   intr   newmaxminwidthheightcroppaste) r>   rD   rE   rF   alphabboxlefttoprightbottomperson_wperson_hpadded_wpadded_hwidth_from_htarget_wtarget_hperson_center_xperson_center_ypad_bias
canvas_topcanvas_bottomcanvas_leftcanvas_rightcanvassrc_left	src_rightsrc_top
src_bottomregiondst_xdst_yr   r   r   r9   ]   sF   



z'SegmentationService._center_crop_personmax_sizec                 C   s~   t t| }|j\}}t|||kr| S |t|| }t|| t|| f}||t j}t }|j	|dd |
 S )zFResize image if too large, preserving format as PNG for alpha support.r1   r2   )r   r5   r6   r7   sizerO   rM   resizeLANCZOSr:   r;   )r*   rq   r>   whrationew_sizer?   r   r   r   r4      s   
z,SegmentationService._resize_for_segmentationN)F)rA   rB   rC   )__name__
__module____qualname____doc__r)   bytesboolr@   staticmethodr   floatr9   MAX_INPUT_SIZErM   r4   r   r   r   r   r      sF    0
Jr   )r|   r6   loggingPILr   rembgr   r   
app.configr   	getLoggerry   r   r   r   r   r   r   r   <module>   s    
