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

    Returns:
    --------
    AI::MXNet::NDArray $resized_image
=cut

method resize_short(AI::MXNet::NDArray $src, Int $size, Int $interp=2)
{
    my ($new_h, $new_w);
    my ($h, $w) = @{ $src->shape };

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

        my $idx = $self->seq->[$self->cur];
        $self->cur($self->cur + 1);
        if(defined $self->imgrec)
        {
            my $s = $self->imgrec->read_idx($idx);
            my ($header, $img) = AI::MXNet::RecordIO->unpack($s);
            if(not defined $self->imglist)
            {
                return ($header->label, $img);
            }
            else
            {
                return ($self->imglist->{$idx}[0], $img);
            }
        }
        else
        {
            my ($label, $fname) = @{ $self->imglist->{$idx} };
            if(not defined $self->imgrec)
            {
                open(F, $self->path_root . "/$fname") or confess("can't open $fname $!");
                my $img;
                { local $/ = undef; $img = <F> };
                close(F);
                return ($label, $img);
            }
        }
    }
    else
    {
        my $s = $self->imgrec->read;
        return undef if(not defined $s);
        my ($header, $img) = AI::MXNet::RecordIO->unpack($s);
        return ($header->label, $img)
    }
}

method next()
{
    my $batch_size = $self->batch_size;
    my ($c, $h, $w) = @{ $self->data_shape };
    my $batch_data  = AI::MXNet::NDArray->empty([$batch_size, $c, $h, $w]);
    my $batch_label = AI::MXNet::NDArray->empty(@{$self->provide_label->[0]}[1]);
    my $i = 0;
    while ($i < $batch_size)
    {
        my ($label, $s) = $self->next_sample;
        last if not defined $label;
        my $data = [AI::MXNet::Image->imdecode($s)];
        if(@{ $data->[0]->shape } == 0)
        {
            AI::MXNet::Logging->debug('Invalid image, skipping.');
            next;
        }
        for my $aug (@{ $self->aug_list })
        {
            $data = [map { @{ $aug->($_) } } @$data];
        }
        for my $d (@$data)
        {
            assert(($i < $batch_size), 'Batch size must be multiples of augmenter output length');
            $batch_data->at($i)  .= AI::MXNet::NDArray->transpose($d, { axes=>[2, 0, 1] });
            $batch_label->at($i) .= $label;
            $i++;
        }
    }
    return undef if not $i;
    return AI::MXNet::DataBatch->new(data=>[$batch_data], label=>[$batch_label], pad => $batch_size-$i);
}

1;



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