AI-MXNet

 view release on metacpan or  search on metacpan

lib/AI/MXNet/Image.pm  view on Meta::CPAN

package AI::MXNet::Image;
use strict;
use warnings;
use Scalar::Util qw(blessed);
use AI::MXNet::Base;
use AI::MXNet::Function::Parameters;

=head1 NAME

    AI::MXNet:Image - Read individual image files and perform augmentations.
=cut

=head2 imdecode

    Decode an image from string. Requires OpenCV to work.

    Parameters
    ----------
    $buf : str, array ref, pdl, ndarray
        Binary image data.
    :$flag : int
        0 for grayscale. 1 for colored.
    :$to_rgb : int
        0 for BGR format (OpenCV default). 1 for RGB format (MXNet default).
    :$out : NDArray
        Output buffer. Do not specify for automatic allocation.
=cut

method imdecode(Str|PDL $buf, Int :$flag=1, Int :$to_rgb=1, Maybe[AI::MXNet::NDArray] :$out=)
{
    if(not ref $buf)
    {
        my $pdl_type = PDL::Type->new(DTYPE_MX_TO_PDL->{'uint8'});
        my $len; { use bytes; $len = length $buf; }
        my $pdl = PDL->new_from_specification($pdl_type, $len);
        ${$pdl->get_dataref} = $buf;
        $pdl->upd_data;
        $buf = $pdl;
    }
    if(not (blessed $buf and $buf->isa('AI::MXNet::NDArray')))
    {
        $buf = AI::MXNet::NDArray->array($buf, dtype=>'uint8');
    }
    return AI::MXNet::NDArray->_cvimdecode($buf, { flag => $flag, to_rgb => $to_rgb, ($out ? (out => $out) : ()) });
}

=head2 scale_down

Scale down crop size if it's bigger than the image size.

    Parameters:
    -----------
    Shape $src_size
    Shape $size

    Returns:
    --------
    ($w, $h)
=cut

method scale_down(Shape $src_size, Shape $size)
{
    my ($w, $h) = @{ $size };
    my ($sw, $sh) = @{ $src_size };
    if($sh < $h)
    {
        ($w, $h) = (($w*$sh)/$h, $sh);
    }
    if($sw < $w)
    {
        ($w, $h) = ($sw, ($h*$sw)/$w);
    }
    return (int($w), int($h));
}

=head2 resize_short

    Resize shorter edge to the size.

    Parameters:
    -----------
    AI::MXNet::NDArray $src
    Int                $size
    Int                $interp=2

lib/AI/MXNet/Image.pm  view on Meta::CPAN

method ImageIter(@args) { AI::MXNet::ImageIter->new(@args) }

package AI::MXNet::ImageIter;
use Mouse;
use AI::MXNet::Base;
extends 'AI::MXNet::DataIter';

=head1 NAME

    AI::MXNet::ImageIter - Image data iterator.
=cut

=head1 DESCRIPTION


    Image data iterator with a large number of augumentation choices.
    Supports reading from both .rec files and raw image files with image list.

    To load from .rec files, please specify path_imgrec. Also specify path_imgidx
    to use data partition (for distributed training) or shuffling.

    To load from raw image files, specify path_imglist and path_root.

    Parameters
    ----------
    batch_size : Int
        Number of examples per batch
    data_shape : Shape
        Data shape in (channels, height, width).
        For now, only RGB image with 3 channels is supported.
    label_width : Int
        dimension of label
    path_imgrec : str
        path to image record file (.rec).
        Created with tools/im2rec.py or bin/im2rec
    path_imglist : str
        path to image list (.lst)
        Created with tools/im2rec.py or with custom script.
        Format: index\t[one or more label separated by \t]\trelative_path_from_root
    imglist: array ref
        a list of image with the label(s)
        each item is a list [imagelabel: float or array ref of float, imgpath]
    path_root : str
        Root folder of image files
    path_imgidx : str
        Path to image index file. Needed for partition and shuffling when using .rec source.
    shuffle : bool
        Whether to shuffle all images at the start of each iteration.
    Can be slow for HDD.
    part_index : int
        Partition index
    num_parts : int
        Total number of partitions.
    data_name='data' Str
    label_name='softmax_label' Str
    kwargs : hash ref with any additional arguments for augmenters
=cut

has 'batch_size'  => (is => 'ro', isa => 'Int',   required => 1);
has 'data_shape'  => (is => 'ro', isa => 'Shape', required => 1);
has 'label_width' => (is => 'ro', isa => 'Int',   default  => 1);
has 'data_name'   => (is => 'ro', isa => 'Str',   default  => 'data');
has 'label_name'  => (is => 'ro', isa => 'Str',   default  => 'softmax_label');
has [qw/path_imgrec
        path_imglist
        path_root
        path_imgidx
    /]            => (is => 'ro', isa => 'Str');
has 'shuffle'     => (is => 'ro', isa => 'Bool', default => 0);
has 'part_index'  => (is => 'ro', isa => 'Int', default => 0);
has 'num_parts'   => (is => 'ro', isa => 'Int', default => 0);
has 'aug_list'    => (is => 'rw', isa => 'ArrayRef[CodeRef]');
has 'imglist'     => (is => 'rw', isa => 'ArrayRef|HashRef');
has 'kwargs'      => (is => 'ro', isa => 'HashRef');
has [qw/imgidx
        imgrec
        seq
        cur
        provide_data
        provide_label
           /]     => (is => 'rw', init_arg => undef);

sub BUILD
{
    my $self = shift;
    assert($self->path_imgrec or $self->path_imglist or ref $self->imglist eq 'ARRAY');
    if($self->path_imgrec)
    {
        print("loading recordio...\n");
        if($self->path_imgidx)
        {
            $self->imgrec(
                AI::MXNet::IndexedRecordIO->new(
                    idx_path => $self->path_imgidx,
                    uri => $self->path_imgrec,
                    flag => 'r'
                )
            );
            $self->imgidx([@{ $self->imgrec->keys }]);
        }
        else
        {
            $self->imgrec(AI::MXNet::RecordIO->new(uri => $self->path_imgrec, flag => 'r'));
        }
    }
    my %imglist;
    my @imgkeys;
    if($self->path_imglist)
    {
        print("loading image list...\n");
        open(my $f, $self->path_imglist) or confess("can't open ${\ $self->path_imglist } : $!");
        while(my $line = <$f>)
        {
            chomp($line);
            my @line = split(/\t/, $line);
            my $label = AI::MXNet::NDArray->array([@line[1..@line-2]]);
            my $key   = $line[0];
            $imglist{$key} = [$label, $line[-1]];
            push @imgkeys, $key;
        }
        $self->imglist(\%imglist);
    }
    elsif(ref $self->imglist eq 'ARRAY')
    {
        print("loading image list...\n");
        my %result;
        my $index = 1;
        for my $img (@{ $self->imglist })
        {
            my $key = $index++;
            my $label;



( run in 1.763 second using v1.01-cache-2.11-cpan-39bf76dae61 )