
    2Vh!                     T    d dl mZ d dlmZ d dlmZ  ed       G d de             Zy)    )backend)keras_export)BaseImagePreprocessingLayerzkeras.layers.Equalizationc                   ~     e Zd ZdZ	 d fd	Zd Zd Zd Zd Zd Z	ddZ
d	 Zd
 Z	 ddZddZ	 ddZ fdZ xZS )Equalizationa  Preprocessing layer for histogram equalization on image channels.

    Histogram equalization is a technique to adjust image intensities to
    enhance contrast by effectively spreading out the most frequent
    intensity values. This layer applies equalization on a channel-wise
    basis, which can improve the visibility of details in images.

    This layer works with both grayscale and color images, performing
    equalization independently on each color channel. At inference time,
    the equalization is consistently applied.

    **Note:** This layer is safe to use inside a `tf.data` pipeline
    (independently of which backend you're using).

    Args:
        value_range: Optional list/tuple of 2 floats specifying the lower
            and upper limits of the input data values. Defaults to `[0, 255]`.
            If the input image has been scaled, use the appropriate range
            (e.g., `[0.0, 1.0]`). The equalization will be scaled to this
            range, and output values will be clipped accordingly.
        bins: Integer specifying the number of histogram bins to use for
            equalization. Defaults to 256, which is suitable for 8-bit images.
            Larger values can provide more granular intensity redistribution.

    Input shape:
        3D (unbatched) or 4D (batched) tensor with shape:
        `(..., height, width, channels)`, in `"channels_last"` format,
        or `(..., channels, height, width)`, in `"channels_first"` format.

    Output shape:
        3D (unbatched) or 4D (batched) tensor with shape:
        `(..., target_height, target_width, channels)`,
        or `(..., channels, target_height, target_width)`,
        in `"channels_first"` format.

    Example:

    ```python
    # Create an equalization layer for standard 8-bit images
    equalizer = keras.layers.Equalization()

    # An image with uneven intensity distribution
    image = [...] # your input image

    # Apply histogram equalization
    equalized_image = equalizer(image)

    # For images with custom value range
    custom_equalizer = keras.layers.Equalization(
        value_range=[0.0, 1.0],  # for normalized images
        bins=128  # fewer bins for more subtle equalization
    )
    custom_equalized = custom_equalizer(normalized_image)
    ```
    c                     t        |   di | || _        | j                  |       t	        j
                  |      | _        y )N )super__init__bins_set_value_ranger   standardize_data_formatdata_format)selfvalue_ranger   r   kwargs	__class__s        o/home/dcms/DCMS/lib/python3.12/site-packages/keras/src/layers/preprocessing/image_preprocessing/equalization.pyr   zEqualization.__init__B   s=     	"6"	k*"::;G    c                     t        |t        t        f      st        | j                  d| z         t        |      dk7  rt        | j                  d| z         t        |      | _        y )NzReceived: value_range=   )
isinstancetuplelist
ValueError_VALUE_RANGE_VALIDATION_ERRORlensortedr   )r   r   s     r   r   zEqualization._set_value_rangeJ   sx    +t}522*;-89  {q 22*;-89  "+.r   c                    | j                   j                  |d      }|\  }}| j                   j                  |d      }| j                   j                  |d      }||z
  |dz
  z  ||z
  z  }| j                   j                  |d      }| j                   j                  j                  |d|dz
        }| j                   j                  j	                  |dg      }t        j                          dk(  r| j                   j                  j                  |d      }	t        |      D ]  }
| j                   j                  | j                   j                  j                  ||
      d      }| j                   j                  j                  |      }| j                   j                  | j                   j                  j                  |      |
k(  d      }|	||z  z   }	 |	S | j                   j                  j                  ||      S )	Nfloat32   int32r   jaxdtype)	minlength)r   castnumpyclipreshapezerosrangeequalsumarangebincount)r   valuesr   nbins	value_min	value_maxscaledindicesflat_indices	histogramimatches	bin_countone_hots                 r   _custom_histogram_fixed_widthz*Equalization._custom_histogram_fixed_widthW   s   ""695*	9LL%%i;	LL%%i;	9$3y97LM,,##FG4,,$$))'1eai@||))11'B4@??%**00g0FI5\ >,,++LL&&,,\1=w !LL..227;	,,++LL&&--e497 &W)<=	>  <<%%.. /  r   c                 L    |\  }}|\  }}||z
  ||z
  z  }|||z  z
  }	||z  |	z   S Nr	   )
r   r2   source_rangetarget_range
source_min
source_max
target_min
target_maxscaleoffsets
             r   _scale_valueszEqualization._scale_valuesv   sH    !-
J!-
Jj(Z*-DEj500~&&r   c                 `   |dk7  r| j                  ||d      }| j                  |d| j                        }| j                  j                  j                  |      }| j                  j                  j                  |dk  || j                  ||            }|dk7  r| j                  |d|      }|S )Nr      )r   r3   r!   )rI   r>   r   r   r)   count_nonzerowhere_apply_equalization)r   channelr   histnonzero_bins	equalizeds         r   _equalize_channelzEqualization._equalize_channel}   s    ("((+xHG11 2 
 ||))77=LL&&,,Aw(@(@$(O
	 ("**9hLIr   c                 <   | j                   j                  j                  |      }| j                   j                  dk(  rQ|dkD  }| j                   j                  j	                  |      }| j                   j                  j                  ||      }nO| j                   j                  j                  || j                   j                  j                  |      d   d         }|d   |z
  }| j                   j                  j                  |dk(  | j                   j                  j                  d|j                        |      }||z
  dz  |z  }| j                   j                  j                  | j                   j                  j                  |      dd      }|dz  | j                  dz
  z  }	| j                   j                  | j                   j                  j                  |	d| j                  dz
        d      }
| j                   j                  j                  ||
      S )	Nr$   r   r#   r!   r%   rL   g     o@r"   )r   r)   cumsumnameargmaxtakenonzerorN   	ones_liker&   r*   roundr   r(   )r   rP   rQ   cdfmaskfirst_nonzero_idxcdf_mindenominatorlookup_tablescaled_channelr7   s              r   rO   z Equalization._apply_equalization   s   ll  ''-<<%7D $ 2 2 9 9$ ?ll((--c3DEGll((--T\\''//4Q7:G "g'll((..1LL((+2C2C(D
 w#-<||))..LL$$\2As
 "E/dii!m<,,##LL##NAtyy1}Ew
 ||!!&&|W==r   c                    |r| j                   j                  || j                        }| j                  dk(  rg }t	        | j                   j
                  j                  |      d         D ]<  }|d|d d d d f   }| j                  || j                        }|j                  |       > | j                   j                  j                  |d      }ng }t	        | j                   j
                  j                  |      d         D ]6  }|d|f   }| j                  || j                        }|j                  |       8 | j                   j                  j                  |d      }| j                   j                  || j                        S |S )Nchannels_first.)axisr#   )r   r(   compute_dtyper   r-   coreshaperT   r   appendr)   stack)	r   imagestransformationtrainingchannelsr:   rP   rS   equalized_imagess	            r   transform_imageszEqualization.transform_images   sn   \\&&vt/A/ABF#33t||0066v>rBC /A$S!Q\2G $ 6 6!1!1!I OOI./ $(<<#5#5#;#;H2#;#N t||0066v>rBC /A$S!VnG $ 6 6!1!1!I OOI./ $(<<#5#5#;#;H2#;#N <<$$%5t7I7IJJr   c                     |S r@   r	   )r   input_shapes     r   compute_output_shapez!Equalization.compute_output_shape   s    r   c                     |S r@   r	   )r   inputsr   s      r   compute_output_specz Equalization.compute_output_spec       r   c                     |S r@   r	   )r   bounding_boxesrn   ro   s       r   transform_bounding_boxesz%Equalization.transform_bounding_boxes   s
     r   c                     |S r@   r	   )r   labelsrn   ro   s       r   transform_labelszEqualization.transform_labels   ry   r   c                     |S r@   r	   )r   segmentation_masksrn   ro   s       r   transform_segmentation_masksz)Equalization.transform_segmentation_masks   s
     "!r   c                 t    t         |          }|j                  | j                  | j                  d       |S )N)r   r   )r
   
get_configupdater   r   )r   configr   s     r   r   zEqualization.get_config   s0    #%tyy9I9IJKr   )rK      N)T)__name__
__module____qualname____doc__r   r   r>   rI   rT   rO   rr   ru   rx   r|   r   r   r   __classcell__)r   s   @r   r   r      s`    6r ;?H/>'$><4 	 <@"
 r   r   N)	keras.srcr   keras.src.api_exportr   Qkeras.src.layers.preprocessing.image_preprocessing.base_image_preprocessing_layerr   r   r	   r   r   <module>r      s5     -
 )*W. W +Wr   