o
    e                     @   sv  d Z ddlmZmZmZ ddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlZddlmZ ddlm
Z ddlmZmZ ejd dkr_ddlZddlmZmZ ddlZej Z!nejd dkrrddlZddl"mZmZ dZ#dd	 Z$d
d Z%dd Z&dd Z'dd Z(G dd de)Z*dd Z+dd Z,dd Z-dd Z.dd Z/d$ddZ0G d d! d!e)Z1G d"d# d#e)Z2dS )%zFClasses and functions dealing with augmentation on multiple CPU cores.    )print_functiondivisionabsolute_importN)BatchUnnormalizedBatch   )EmptyFull   c                  C   sX   t j} | d dkp| d dko| d dk}d }dt v r&d}|r&td |r*dS |S )	Nr   r   r
      ZNixOSZspawnzDetected usage of imgaug.multicore in python <=3.4 and NixOS. This is known to sometimes cause endlessly hanging programs when also making use of multicore augmentation (aka background augmentation). Use python 3.5 or later to prevent this.F)sysversion_infoplatformversioniawarn)ZvinfoZget_context_unsupportedmethod r   @D:\Projects\ConvertPro\env\Lib\site-packages\imgaug/multicore.py_get_context_method!   s   	
r   c                 C   s    | du rt nt | t d< d S )NF_CONTEXT)multiprocessingZget_contextglobals)r   r   r   r   _set_contextB   s   r   c                   C   s   d t  d< d S )Nr   )r   r   r   r   r   _reset_contextK      r   c                   C   s   t t  d S N)r   r   r   r   r   r   _autoset_contextP   r   r   c                   C   s   t d u rt  t S r   )r   r   r   r   r   r   _get_contextU   s   r   c                   @   s   e Zd ZdZdZdZ		d$ddZedd Zd%ddZ			d$d	d
Z
edd Zd&ddZ		d&ddZedd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zed"d# ZdS )'Poolax  
    Wrapper around ``multiprocessing.Pool`` for multicore augmentation.

    Parameters
    ----------
    augseq : imgaug.augmenters.meta.Augmenter
        The augmentation sequence to apply to batches.

    processes : None or int, optional
        The number of background workers, similar to the same parameter in
        multiprocessing.Pool. If ``None``, the number of the machine's CPU
        cores will be used (this counts hyperthreads as CPU cores). If this is
        set to a negative value ``p``, then ``P - abs(p)`` will be used,
        where ``P`` is the number of CPU cores. E.g. ``-1`` would use all
        cores except one (this is useful to e.g. reserve one core to feed
        batches to the GPU).

    maxtasksperchild : None or int, optional
        The number of tasks done per worker process before the process is
        killed and restarted, similar to the same parameter in
        multiprocessing.Pool. If ``None``, worker processes will not be
        automatically restarted.

    seed : None or int, optional
        The seed to use for child processes. If ``None``, a random seed will
        be used.

    Nc                 C   s   t jd u s	J d|d u s|dksJ dt|t|f || _|| _|| _|d urGtj|  kr6tj	ksGn J dtjtj	t|t|f || _
d | _d| _d S )Nzm_WORKER_AUGSEQ was already set when calling Pool.__init__(). Did you try to instantiate a Pool within a Pool?r   zExpected `processes` to be `None` ("use as many cores as available") or a negative integer ("use as many as available MINUS this number") or an integer>1 ("use exactly that many processes"). Got type %s, value %s instead.z`Expected `seed` to be either `None` or a value between %d and %d. Got type %s, value %s instead.)r   _WORKER_AUGSEQtypestraugseq	processesmaxtasksperchildiarandomSEED_MIN_VALUESEED_MAX_VALUEseed_pool
_batch_idx)selfr#   r$   r%   r)   r   r   r   __init__   s2   	
zPool.__init__c              	   C   s   | j du rC| j}|dur3|dk r3zt  t| }t|d}W n ttfy2   t	d d}Y nw t j
|t| j| jf| jd| _ | j S )a  Return or create the ``multiprocessing.Pool`` instance.

        This creates a new instance upon the first call and afterwards
        returns that instance (until the property ``_pool`` is set to
        ``None`` again).

        Returns
        -------
        multiprocessing.Pool
            The ``multiprocessing.Pool`` used internally by this
            ``imgaug.multicore.Pool``.

        Nr   r   zCould not find method multiprocessing.cpu_count(). This will likely lead to more CPU cores being used for the background augmentation than originally intended.)ZinitializerZinitargsr%   )r*   r$   r   	cpu_countabsmaxImportErrorNotImplementedErrorr   r   r   _Pool_initialize_workerr#   r)   r%   )r,   r$   r   r   r   pool   s&   

z	Pool.poolc                 C   s"   |  | | jjt| ||dS )a  
        Augment a list of batches.

        Parameters
        ----------
        batches : list of imgaug.augmentables.batches.Batch
            The batches to augment.

        chunksize : None or int, optional
            Rough indicator of how many tasks should be sent to each worker.
            Increasing this number can improve performance.

        Returns
        -------
        list of imgaug.augmentables.batches.Batch
            Augmented batches.

        	chunksize)_assert_batches_is_listr4   map_Pool_starworker_handle_batch_ids)r,   batchesr6   r   r   r   map_batches   s   
zPool.map_batchesc                 C   s&   |  | | jjt| ||||dS )a  
        Augment batches asynchonously.

        Parameters
        ----------
        batches : list of imgaug.augmentables.batches.Batch
            The batches to augment.

        chunksize : None or int, optional
            Rough indicator of how many tasks should be sent to each worker.
            Increasing this number can improve performance.

        callback : None or callable, optional
            Function to call upon finish. See ``multiprocessing.Pool``.

        error_callback : None or callable, optional
            Function to call upon errors. See ``multiprocessing.Pool``.

        Returns
        -------
        multiprocessing.MapResult
            Asynchonous result. See ``multiprocessing.Pool``.

        )r6   callbackerror_callback)r7   r4   Z	map_asyncr9   r:   )r,   r;   r6   r=   r>   r   r   r   map_batches_async   s   
zPool.map_batches_asyncc                 C   s    t |tsJ dt|f d S )NzXExpected `batches` to be a list, got type %s. Call imap_batches() if you use generators.)
isinstancelistr!   clsr;   r   r   r   r7        
zPool._assert_batches_is_listr   c                 c   X    |  | t|}| jjt| | |||d}|D ]}|V  |dur)|  qdS )aQ  
        Augment batches from a generator.

        Pattern for output buffer constraint is from
        https://stackoverflow.com/a/47058399.

        Parameters
        ----------
        batches : generator of imgaug.augmentables.batches.Batch
            The batches to augment, provided as a generator. Each call to the
            generator should yield exactly one batch.

        chunksize : None or int, optional
            Rough indicator of how many tasks should be sent to each worker.
            Increasing this number can improve performance.

        output_buffer_size : None or int, optional
            Max number of batches to handle *at the same time* in the *whole*
            pipeline (including already augmented batches that are waiting to
            be requested). If the buffer size is reached, no new batches will
            be loaded from `batches` until a produced (i.e. augmented) batch is
            consumed (i.e. requested from this method).
            The buffer is unlimited if this is set to ``None``. For large
            datasets, this should be set to an integer value to avoid filling
            the whole RAM if loading+augmentation happens faster than training.

            *New in version 0.3.0.*

        Yields
        ------
        imgaug.augmentables.batches.Batch
            Augmented batch.

        r5   N)_assert_batches_is_generator_create_output_buffer_leftr4   imapr9   _ibuffer_batch_loading_handle_batch_ids_genreleaser,   r;   r6   output_buffer_sizeoutput_buffer_leftgenbatchr   r   r   imap_batches  s"   
#zPool.imap_batchesc                 c   rE   )ah  Augment batches from a generator (without preservation of order).

        Pattern for output buffer constraint is from
        https://stackoverflow.com/a/47058399.

        Parameters
        ----------
        batches : generator of imgaug.augmentables.batches.Batch
            The batches to augment, provided as a generator. Each call to the
            generator should yield exactly one batch.

        chunksize : None or int, optional
            Rough indicator of how many tasks should be sent to each worker.
            Increasing this number can improve performance.

        output_buffer_size : None or int, optional
            Max number of batches to handle *at the same time* in the *whole*
            pipeline (including already augmented batches that are waiting to
            be requested). If the buffer size is reached, no new batches will
            be loaded from `batches` until a produced (i.e. augmented) batch is
            consumed (i.e. requested from this method).
            The buffer is unlimited if this is set to ``None``. For large
            datasets, this should be set to an integer value to avoid filling
            the whole RAM if loading+augmentation happens faster than training.

            *New in version 0.3.0.*

        Yields
        ------
        imgaug.augmentables.batches.Batch
            Augmented batch.

        r5   N)rF   rG   r4   Zimap_unorderedr9   rI   rJ   rK   rL   r   r   r   imap_batches_unorderedS  s"   
#	zPool.imap_batches_unorderedc                 C   s    t |sJ dt|f d S )NzUExpected `batches` to be generator, got type %s. Call map_batches() if you use lists.)r   is_generatorr!   rB   r   r   r   rF     rD   z!Pool._assert_batches_is_generatorc                 C   s   | j d u s	J d| j}| S )Nz<Tried to __enter__ a pool that has already been initialized.)r*   r4   )r,   _r   r   r   	__enter__  s
   zPool.__enter__c                 C   s   |    d S r   )close)r,   exc_typeexc_valexc_tbr   r   r   __exit__     zPool.__exit__c                 C   ,   | j dur| j   | j   d| _ dS dS )zClose the pool gracefully.N)r*   rV   joinr,   r   r   r   rV     
   



z
Pool.closec                 C   r\   )zTerminate the pool immediately.N)r*   	terminater]   r^   r   r   r   r`     r_   zPool.terminatec                 C   s   | j dur| j   dS dS )z
        Wait for the workers to exit.

        This may only be called after first calling
        :func:`~imgaug.multicore.Pool.close` or
        :func:`~imgaug.multicore.Pool.terminate`.

        N)r*   r]   r^   r   r   r   r]     s   
	z	Pool.joinc                 C   s<   t | j| jt| }tt||}|  jt|7  _|S r   )npZaranger+   lenrA   zip)r,   r;   Zidsinputsr   r   r   r:     s   zPool._handle_batch_idsc                 c   s.    |D ]}| j }||fV  |  j d7  _ qd S )Nr   )r+   )r,   r;   rP   	batch_idxr   r   r   rJ     s   
zPool._handle_batch_ids_genc                 c   s&    |D ]}|d ur|   |V  qd S r   )acquire)rC   r;   rN   rP   r   r   r   rI     s   zPool._ibuffer_batch_loading)NNNr   )r   N)__name__
__module____qualname____doc__r    _WORKER_SEED_STARTr-   propertyr4   r<   r?   classmethodr7   rQ   rR   rF   rU   rZ   rV   r`   r]   r:   rJ   rI   r   r   r   r   r   [   s<    !
'

.
"

6
6
	r   c                 C   s.   d }| r| dksJ d| f t  | }|S )Nr   zFExpected buffer size to be greater than zero, but got size %d instead.)r   	Semaphore)rM   rN   r   r   r   rG     s   
rG   c                 C   s   t d |d u r7t  j}tjd dkr"tjd dkr"t }n
t	t d d }t
|| }t||  |t_| t_tj  d S )Nr   r
   r      i@B )cv2ZsetNumThreadsr   current_processnamer   r   timetime_nsinthash_reseed_global_localr   rk   r    Zlocalize_random_state_)r#   Z
seed_startZprocess_nameZseed_offsetr)   r   r   r   r3     s   


r3   c                 C   s|   t | sJ dt|  t|ttfsJ dt| tjd us%J dtj}tjd ur7tj|  }t	|| |
|}|S )Nz;Expected `batch_idx` to be an integer. Got type %s instead.zExpected `batch` to be either an instance of `imgaug.augmentables.batches.UnnormalizedBatch` or `imgaug.augmentables.batches.Batch`. Got type %s instead.zVExpected `Pool._WORKER_AUGSEQ` to NOT be `None`. Did you manually call _Pool_worker()?)r   Zis_single_integerr!   r@   r   r   r   r    rk   rw   augment_batch_)re   rP   r#   r)   resultr   r   r   _Pool_worker  s&   



rz   c                 C   s   t |  S r   )rz   )rd   r   r   r   r9     s   r9   c                 C   s*   t | d}t | }t| || d S )Ni 6e)_derive_seedr&   r)   seed_)	base_seedr#   Zseed_globalZ
seed_localr   r   r   rw     s   

rw   c                 C   s   t j| | t jt j   S r   )r&   r'   r(   )r}   offsetr   r   r   r{     s   
r{   c                   @   s^   e Zd ZdZejdd		dddZd	d
 Zdd Zdd Z	e
dd Zdd Zdd ZdS )BatchLoadera  **Deprecated**. Load batches in the background.

    Deprecated. Use ``imgaug.multicore.Pool`` instead.

    Loaded batches can be accesses using :attr:`imgaug.BatchLoader.queue`.

    Parameters
    ----------
    load_batch_func : callable or generator
        Generator or generator function (i.e. function that yields Batch
        objects) or a function that returns a list of Batch objects.
        Background loading automatically stops when the last batch was yielded
        or the last batch in the list was reached.

    queue_size : int, optional
        Maximum number of batches to store in the queue. May be set higher
        for small images and/or small batches.

    nb_workers : int, optional
        Number of workers to run in the background.

    threaded : bool, optional
        Whether to run the background processes using threads (True) or full
        processes (False).

    imgaug.multicore.PoolZalt_func2   r   Tc                 C   s  |dksJ d|f |dksJ d|f t |d | _t |d | _t  | _g | _|| _t	 
|}t|D ]0}|rOtj| j|| j| jd fd}nt j| j|| j| j|| fd}d|_|  | j| q<tj| jdd| _d| j_| j  d S )Nr   z6Queue size for BatchLoader must be at least 2, got %d.r   z<Number of workers for BatchLoader must be at least 1, got %dtargetargsTr   )r   Queue_queue_internalqueueEventjoin_signalworkersthreadedr&   get_global_rnggenerate_seeds_range	threadingThread_load_batchesProcessdaemonstartappend_main_workermain_worker_thread)r,   load_batch_func
queue_size
nb_workersr   seedsiworkerr   r   r   r-   @  sN   



zBatchLoader.__init__c                 C   s   t dd | jD S )Nc                 S   s   g | ]}t | qS r   )ru   is_alive).0r   r   r   r   
<listcomp>h  s    z3BatchLoader.count_workers_alive.<locals>.<listcomp>)sumr   r^   r   r   r   count_workers_aliveg  s   zBatchLoader.count_workers_alivec                 C   s   |   dkS )z
        Determine whether the workers have finished the loading process.

        Returns
        -------
        out : bool
            True if all workers have finished. Else False.

        r   )r   r^   r   r   r   all_finishedj  s   
zBatchLoader.all_finishedc              	   C   s  |   }|dkrK| j sKz| jjdd}|dkr|d8 }n| j| W n ty3   t	d Y n t
tfy=   Y nw |   }|dkrK| j r	 z| jjdd}|dkr^| j| W n tyh   Y n t
tfyr   Y nw qL| jtjd d	d
 t	d d S )Nr   皙?timeout r   {Gz?T{Gzt?protocol)r   r   is_setr   getr   put
QueueEmptyrs   sleepEOFErrorBrokenPipeErrorpickledumps)r,   Zworkers_running	batch_strr   r   r   r   v  s:   

zBatchLoader._main_workerc              	   C   s   |d urt | tj | t| z\zGt|s| n|}|D ]8}t|ts2J dt|f t	j
|dd}| sTz	|j|dd W n tyO   Y nw | r=| rZ nq"W n tyi   t  Y nw W |d n|d w td d S )NzOExpected batch returned by load_batch_func to be of class imgaug.Batch, got %s.r   r   r   r   r   r   )randomr)   ra   r&   r   rS   r@   r   r!   r   r   r   r   	QueueFull	Exception	traceback	print_excrs   r   )rC   r   Zqueue_internalr   seedvalrO   rP   Zbatch_pickledr   r   r   r     sF   

zBatchLoader._load_batchesc                 C   s8  | j  s
| j   td | j r| j  | jr+| j	D ]
}| r)|  qn| j	D ]}| r<|
  |  q.|  sJtd |  rA| j rT| j  | jtjddd td 	 z	| jjdd W n	 tyw   Y nw qe| jjs| j  | jjs| j  | j  | j  td	 dS )
zStop all workers.r   MbP?Nr   r   Tr   r   g?)r   r   setrs   r   r   r   r]   r   r   r`   r   r   fullr   r   r   r   r   r   _closedrV   Zjoin_threadr,   r   r   r   r   r`     sJ   














zBatchLoader.terminatec                 C   s   | j  s| j   d S d S r   )r   r   r   r^   r   r   r   __del__  s   
zBatchLoader.__del__N)r   r   T)rg   rh   ri   rj   r   
deprecatedr-   r   r   r   rm   r   r`   r   r   r   r   r   r   $  s    
&!
"0r   c                   @   sR   e Zd ZdZejdddddZdd	 Zd
d Ze	dd Z
dd Zdd ZdS )BackgroundAugmentera  
    **Deprecated**. Augment batches in the background processes.

    Deprecated. Use ``imgaug.multicore.Pool`` instead.

    This is a wrapper around the multiprocessing module.

    Parameters
    ----------
    batch_loader : BatchLoader or multiprocessing.Queue
        BatchLoader object that loads the data fed into the
        BackgroundAugmenter, or alternatively a Queue. If a Queue, then it
        must be made sure that a final ``None`` in the Queue signals that the
        loading is finished and no more batches will follow. Otherwise the
        BackgroundAugmenter will wait forever for the next batch.

    augseq : Augmenter
        An augmenter to apply to all loaded images.
        This may be e.g. a Sequential to apply multiple augmenters.

    queue_size : int
        Size of the queue that is used to temporarily save the augmentation
        results. Larger values offer the background processes more room
        to save results when the main process doesn't load much, i.e. they
        can lead to smoother and faster training. For large images, high
        values can block a lot of RAM though.

    nb_workers : 'auto' or int
        Number of background workers to spawn.
        If ``auto``, it will be set to ``C-1``, where ``C`` is the number of
        CPU cores.

    r   r   r   autoc              	   C   s  |dksJ d|f || _ t|tjjr|n|j| _t|| _|dkrAzt }W n t	t
fy8   d}Y nw td|d }n|dksLJ d|f || _g | _d| _t |}t|D ]}tj| j|| j| j|| fd}d|_|  | j| q`d S )Nr   z/Expected 'queue_size' to be at least 1, got %d.r   r   zAExpected 'nb_workers' to be "auto" or at least 1, got %d instead.r   T)r#   r@   r   queuesr   r   queue_sourcequeue_resultr.   r1   r2   r0   r   r   nb_workers_finishedr&   r   r   r   r   _augment_images_workerr   r   r   )r,   Zbatch_loaderr#   r   r   r   r   r   r   r   r   r-     sD   

zBackgroundAugmenter.__init__c                 C   s   | j | jkS r   )r   r   r^   r   r   r   r   8  r[   z BackgroundAugmenter.all_finishedc                 C   sx   |   rdS | j }t|}|dur|S |  jd7  _| j| jkr8z
| jjdd W dS  ty7   Y dS w | 	 S )aK  
        Returns a batch from the queue of augmented batches.

        If workers are still running and there are no batches in the queue,
        it will automatically wait for the next batch.

        Returns
        -------
        out : None or imgaug.Batch
            One batch or None if all workers have finished.

        Nr   r   r   )
r   r   r   r   loadsr   r   r   r   	get_batch)r,   r   rP   r   r   r   r   ;  s    

zBackgroundAugmenter.get_batchc           	      C   s   t j| t| || t| d}|sYz/|jdd}t|}|du r6d}|tj	ddd n|
|}tj	|dd}|| W n tyV   td Y nw |r|tj	ddd td dS )	z
        Augment endlessly images in the source queue.

        This is a worker function for that endlessly queries the source queue
        (input batches), augments batches in it and sends the result to the
        output queue.

        Fr   r   NTr   r   r   )ra   r   r)   r|   r&   r   r   r   r   r   rx   r   rs   r   )	rC   r#   r   r   r   Zloader_finishedr   rP   Z	batch_augr   r   r   r   Z  s,   





z*BackgroundAugmenter._augment_images_workerc                 C   sH   | j D ]
}| r|  qt| j | _| jjs| j  t	d dS )zk
        Terminates all background processes immediately.

        This will also free their RAM.

        r   N)
r   r   r`   rb   r   r   r   rV   rs   r   r   r   r   r   r`     s   

zBackgroundAugmenter.terminatec                 C   s   t d |   d S )Nr   )rs   r   r`   r^   r   r   r   r     s   
zBackgroundAugmenter.__del__N)r   r   )rg   rh   ri   rj   r   r   r-   r   r   rm   r   r`   r   r   r   r   r   r     s    
"%
'r   )r   )3rj   
__future__r   r   r   r   r   r   r   rs   r   r   numpyra   rp   Zimgaug.imgaugZimgaugr   Zimgaug.randomr&   Zimgaug.augmentables.batchesr   r   r   cPickler   r   r   r   r	   r   socketerrorr   r   r   r   r   r   r   r   objectr   rG   r3   rz   r9   rw   r{   r   r   r   r   r   r   <module>   sP    !	  o 
 L