예제 #1
0
bool
ImageBufAlgo::compare (const ImageBuf &A, const ImageBuf &B,
                       float failthresh, float warnthresh,
                       ImageBufAlgo::CompareResults &result,
                       ROI roi, int nthreads)
{
    // If no ROI is defined, use the union of the data windows of the two
    // images.
    if (! roi.defined())
        roi = roi_union (get_roi(A.spec()), get_roi(B.spec()));
    roi.chend = std::min (roi.chend, std::max(A.nchannels(), B.nchannels()));

    // Deep and non-deep images cannot be compared
    if (B.deep() != A.deep())
        return false;

    bool ok;
    OIIO_DISPATCH_TYPES2 (ok, "compare", compare_,
                          A.spec().format, B.spec().format,
                          A, B, failthresh, warnthresh, result,
                          roi, nthreads);
    // FIXME - The nthreads argument is for symmetry with the rest of
    // ImageBufAlgo and for future expansion. But for right now, we
    // don't actually split by threads.  Maybe later.
    return ok;
}
예제 #2
0
/// Fix all non-finite pixels (nan/inf) using the specified approach
bool
ImageBufAlgo::fixNonFinite (ImageBuf &src, 
                            NonFiniteFixMode mode, int *pixelsFixed,
                            ROI roi, int nthreads)
{
    // If no ROI is defined, use the data window of src.
    if (! roi.defined())
        roi = get_roi(src.spec());
    roi.chend = std::min (roi.chend, src.nchannels());

    // Initialize
    if (pixelsFixed)
        *pixelsFixed = 0;

    switch (src.spec().format.basetype) {
    case TypeDesc::FLOAT :
        return fixNonFinite_<float> (src, mode, pixelsFixed, roi, nthreads);
    case TypeDesc::HALF  :
        return fixNonFinite_<half> (src, mode, pixelsFixed, roi, nthreads);
    case TypeDesc::DOUBLE:
        return fixNonFinite_<double> (src, mode, pixelsFixed, roi, nthreads);
    default:
        // All other format types aren't capable of having nonfinite
        // pixel values.
        return true;
    }
}
bool
ImageBufAlgo::transpose (ImageBuf &dst, const ImageBuf &src,
                         ROI roi, int nthreads)
{
    pvt::LoggedTimer logtime("IBA::transpose");
    if (! roi.defined())
        roi = get_roi (src.spec());
    roi.chend = std::min (roi.chend, src.nchannels());
    ROI dst_roi (roi.ybegin, roi.yend, roi.xbegin, roi.xend,
                 roi.zbegin, roi.zend, roi.chbegin, roi.chend);
    bool dst_initialized = dst.initialized();
    if (! IBAprep (dst_roi, &dst))
        return false;
    if (! dst_initialized) {
        ROI r = src.roi_full();
        ROI dst_roi_full (r.ybegin, r.yend, r.xbegin, r.xend,
                          r.zbegin, r.zend, r.chbegin, r.chend);
        dst.set_roi_full (dst_roi_full);
    }
    bool ok;
    if (dst.spec().format == src.spec().format) {
        OIIO_DISPATCH_TYPES (ok, "transpose", transpose_, dst.spec().format,
                             dst, src, roi, nthreads);
    } else {
        OIIO_DISPATCH_COMMON_TYPES2 (ok, "transpose", transpose_, dst.spec().format,
                              src.spec().format, dst, src, roi, nthreads);
    }
    return ok;
}
예제 #4
0
bool
ImageBufAlgo::transpose (ImageBuf &dst, const ImageBuf &src,
                         ROI roi, int nthreads)
{
    if (! roi.defined())
        roi = get_roi (src.spec());
    roi.chend = std::min (roi.chend, src.nchannels());
    ROI dst_roi (roi.ybegin, roi.yend, roi.xbegin, roi.xend,
                 roi.zbegin, roi.zend, roi.chbegin, roi.chend);
    IBAprep (dst_roi, &dst);
    OIIO_DISPATCH_TYPES2 ("transpose", transpose_, dst.spec().format,
                          src.spec().format, dst, src, roi, nthreads);
    return false;
}
예제 #5
0
bool
ImageBufAlgo::isMonochrome (const ImageBuf &src, ROI roi, int nthreads)
{
    // If no ROI is defined, use the data window of src.
    if (! roi.defined())
        roi = get_roi(src.spec());
    roi.chend = std::min (roi.chend, src.nchannels());
    if (roi.nchannels() < 2)
        return true;  // 1 or fewer channels are always "monochrome"

    OIIO_DISPATCH_TYPES ("isMonochrome", isMonochrome_, src.spec().format,
                         src, roi, nthreads);
    // FIXME -  The nthreads argument is for symmetry with the rest of
    // ImageBufAlgo and for future expansion. But for right now, we
    // don't actually split by threads.  Maybe later.
};
예제 #6
0
bool
ImageBufAlgo::color_count (const ImageBuf &src, imagesize_t *count,
                           int ncolors, const float *color,
                           const float *eps,
                           ROI roi, int nthreads)
{
    // If no ROI is defined, use the data window of src.
    if (! roi.defined())
        roi = get_roi(src.spec());
    roi.chend = std::min (roi.chend, src.nchannels());

    if (! eps) {
        float *localeps = ALLOCA (float, roi.chend);
        for (int c = 0;  c < roi.chend;  ++c)
            localeps[c] = 0.001f;
        eps = localeps;
    }
예제 #7
0
static bool
convolve_ (ImageBuf &dst, const ImageBuf &src, const ImageBuf &kernel,
           bool normalize, ROI roi, int nthreads)
{
    if (nthreads != 1 && roi.npixels() >= 1000) {
        // Lots of pixels and request for multi threads? Parallelize.
        ImageBufAlgo::parallel_image (
            boost::bind(convolve_<DSTTYPE,SRCTYPE>, boost::ref(dst),
                        boost::cref(src), boost::cref(kernel), normalize,
                        _1 /*roi*/, 1 /*nthreads*/),
            roi, nthreads);
        return true;
    }

    // Serial case

    float scale = 1.0f;
    if (normalize) {
        scale = 0.0f;
        for (ImageBuf::ConstIterator<float> k (kernel); ! k.done(); ++k)
            scale += k[0];
        scale = 1.0f / scale;
    }

    float *sum = ALLOCA (float, roi.chend);
    ROI kroi = get_roi (kernel.spec());
    ImageBuf::Iterator<DSTTYPE> d (dst, roi);
    ImageBuf::ConstIterator<SRCTYPE> s (src, roi, ImageBuf::WrapClamp);
    for ( ; ! d.done();  ++d) {

        for (int c = roi.chbegin; c < roi.chend; ++c)
            sum[c] = 0.0f;

        for (ImageBuf::ConstIterator<float> k (kernel, kroi); !k.done(); ++k) {
            float kval = k[0];
            s.pos (d.x() + k.x(), d.y() + k.y(), d.z() + k.z());
            for (int c = roi.chbegin; c < roi.chend; ++c)
                sum[c] += kval * s[c];
        }
        
        for (int c = roi.chbegin; c < roi.chend; ++c)
            d[c] = scale * sum[c];
    }

    return true;
}
예제 #8
0
bool
ImageBufAlgo::isConstantChannel (const ImageBuf &src, int channel, float val,
                                 ROI roi, int nthreads)
{
    // If no ROI is defined, use the data window of src.
    if (! roi.defined())
        roi = get_roi(src.spec());

    if (channel < 0 || channel >= src.nchannels())
        return false;  // that channel doesn't exist in the image

    OIIO_DISPATCH_TYPES ("isConstantChannel", isConstantChannel_,
                         src.spec().format, src, channel, val, roi, nthreads);
    // FIXME -  The nthreads argument is for symmetry with the rest of
    // ImageBufAlgo and for future expansion. But for right now, we
    // don't actually split by threads.  Maybe later.
};
예제 #9
0
bool
ImageBufAlgo::isConstantColor (const ImageBuf &src, float *color,
                               ROI roi, int nthreads)
{
    // If no ROI is defined, use the data window of src.
    if (! roi.defined())
        roi = get_roi(src.spec());
    roi.chend = std::min (roi.chend, src.nchannels());

    if (roi.nchannels() == 0)
        return true;
    
    OIIO_DISPATCH_TYPES ("isConstantColor", isConstantColor_,
                         src.spec().format, src, color, roi, nthreads);
    // FIXME -  The nthreads argument is for symmetry with the rest of
    // ImageBufAlgo and for future expansion. But for right now, we
    // don't actually split by threads.  Maybe later.
};
예제 #10
0
bool
ImageBufAlgo::computePixelStats (PixelStats &stats, const ImageBuf &src,
                                 ROI roi, int nthreads)
{
    if (! roi.defined())
        roi = get_roi (src.spec());
    else
        roi.chend = std::min (roi.chend, src.nchannels());
    int nchannels = src.spec().nchannels;
    if (nchannels == 0) {
        src.error ("%d-channel images not supported", nchannels);
        return false;
    }

    OIIO_DISPATCH_TYPES ("computePixelStats", computePixelStats_,
                         src.spec().format, src, stats, roi, nthreads);
    return false;
}
예제 #11
0
bool
ImageBufAlgo::channel_sum (ImageBuf &dst, const ImageBuf &src,
                           const float *weights, ROI roi, int nthreads)
{
    if (! roi.defined())
        roi = get_roi(src.spec());
    roi.chend = std::min (roi.chend, src.nchannels());
    ROI dstroi = roi;
    dstroi.chbegin = 0;
    dstroi.chend = 1;
    if (! IBAprep (dstroi, &dst))
        return false;

    if (! weights) {
        float *local_weights = ALLOCA (float, roi.chend);
        for (int c = 0; c < roi.chend; ++c)
            local_weights[c] = 1.0f;
        weights = &local_weights[0];
    }
예제 #12
0
bool
ImageBufAlgo::paste (ImageBuf &dst, int xbegin, int ybegin,
                     int zbegin, int chbegin,
                     const ImageBuf &src, ROI srcroi, int nthreads)
{
    if (! srcroi.defined())
        srcroi = get_roi(src.spec());

    ROI dstroi (xbegin, xbegin+srcroi.width(),
                ybegin, ybegin+srcroi.height(),
                zbegin, zbegin+srcroi.depth(),
                chbegin, chbegin+srcroi.nchannels());
    ROI dstroi_save = dstroi;  // save the original
    IBAprep (dstroi, &dst);

    // do the actual copying
    OIIO_DISPATCH_TYPES2 ("paste", paste_, dst.spec().format, src.spec().format,
                          dst, dstroi_save, src, srcroi, nthreads);
    return false;
}
예제 #13
0
bool
ImageBufAlgo::histogram (const ImageBuf &A, int channel,
                         std::vector<imagesize_t> &histogram, int bins,
                         float min, float max, imagesize_t *submin,
                         imagesize_t *supermax, ROI roi)
{
    if (A.spec().format != TypeDesc::TypeFloat) {
        A.error ("Unsupported pixel data format '%s'", A.spec().format);
        return false;
    }

    if (A.nchannels() == 0) {
        A.error ("Input image must have at least 1 channel");
        return false;
    }

    if (channel < 0 || channel >= A.nchannels()) {
        A.error ("Invalid channel %d for input image with channels 0 to %d",
                  channel, A.nchannels()-1);
        return false;
    }

    if (bins < 1) {
        A.error ("The number of bins must be at least 1");
        return false;
    }

    if (max <= min) {
        A.error ("Invalid range, min must be strictly smaller than max");
        return false;
    }

    // Specified ROI -> use it. Unspecified ROI -> initialize from A.
    if (! roi.defined())
        roi = get_roi (A.spec());

    histogram_impl<float> (A, channel, histogram, bins, min, max,
                                  submin, supermax, roi);

    return ! A.has_error();
}
예제 #14
0
bool
ImageBufAlgo::transpose (ImageBuf &dst, const ImageBuf &src,
                         ROI roi, int nthreads)
{
    if (! roi.defined())
        roi = get_roi (src.spec());
    roi.chend = std::min (roi.chend, src.nchannels());
    ROI dst_roi (roi.ybegin, roi.yend, roi.xbegin, roi.xend,
                 roi.zbegin, roi.zend, roi.chbegin, roi.chend);
    bool dst_initialized = dst.initialized();
    IBAprep (dst_roi, &dst);
    if (! dst_initialized) {
        ROI r = src.roi_full();
        ROI dst_roi_full (r.ybegin, r.yend, r.xbegin, r.xend,
                          r.zbegin, r.zend, r.chbegin, r.chend);
        dst.set_roi_full (dst_roi_full);
    }
    bool ok;
    OIIO_DISPATCH_TYPES2 (ok, "transpose", transpose_, dst.spec().format,
                          src.spec().format, dst, src, roi, nthreads);
    return ok;
}
예제 #15
0
bool
ImageBufAlgo::zover (ImageBuf &R, const ImageBuf &A, const ImageBuf &B,
                     bool z_zeroisinf, ROI roi, int nthreads)
{
    const ImageSpec &specR = R.spec();
    const ImageSpec &specA = A.spec();
    const ImageSpec &specB = B.spec();

    int nchannels_R, nchannels_A, nchannels_B;
    int alpha_R, alpha_A, alpha_B;
    int z_R, z_A, z_B;
    int colors_R, colors_A, colors_B;
    bool initialized_R = decode_over_channels (R, nchannels_R, alpha_R,
                                               z_R, colors_R);
    bool initialized_A = decode_over_channels (A, nchannels_A, alpha_A,
                                               z_A, colors_A);
    bool initialized_B = decode_over_channels (B, nchannels_B, alpha_B,
                                               z_B, colors_B);

    if (! initialized_A || ! initialized_B) {
        R.error ("Can't 'zover' uninitialized images");
        return false;
    }
    // Fail if the input images don't have a Z channel.
    if (z_A < 0 || z_B < 0 || (initialized_R && z_R < 0)) {
        R.error ("'zover' requires Z channels");
        return false;
    }
    // Fail if the input images don't have an alpha channel.
    if (alpha_A < 0 || alpha_B < 0 || (initialized_R && alpha_R < 0)) {
        R.error ("'zover' requires alpha channels");
        return false;
    }
    // Fail for mismatched channel counts
    if (colors_A != colors_B || colors_A < 1) {
        R.error ("Can't 'zover' images with mismatched color channel counts (%d vs %d)",
                 colors_A, colors_B);
        return false;
    }
    // Fail for unaligned alpha or z channels
    if (alpha_A != alpha_B || z_A != z_B ||
        (initialized_R && alpha_R != alpha_A) ||
        (initialized_R && z_R != z_A)) {
        R.error ("Can't 'zover' images with mismatched channel order",
                 colors_A, colors_B);
        return false;
    }
    
    // At present, this operation only supports ImageBuf's containing
    // float pixel data.
    if ((initialized_R && specR.format != TypeDesc::TypeFloat) ||
        specA.format != TypeDesc::TypeFloat ||
        specB.format != TypeDesc::TypeFloat) {
        R.error ("Unsupported pixel data format combination '%s = %s zover %s'",
                 specR.format, specA.format, specB.format);
        return false;
    }

    // Uninitialized R -> size it to the union of A and B.
    if (! initialized_R) {
        ImageSpec newspec = specA;
        set_roi (newspec, roi_union (get_roi(specA), get_roi(specB)));
        R.reset ("zover", newspec);
    }

    // Specified ROI -> use it. Unspecified ROI -> initialize from R.
    if (! roi.defined())
        roi = get_roi (R.spec());

    parallel_image (boost::bind (over_impl<float,float,float>, boost::ref(R),
                                 boost::cref(A), boost::cref(B), _1,
                                 true, z_zeroisinf),
                    roi, nthreads);
    return ! R.has_error();
}
예제 #16
0
std::string
ImageBufAlgo::computePixelHashSHA1 (const ImageBuf &src,
                                    const std::string & extrainfo,
                                    ROI roi, int blocksize, int nthreads)
{
    if (! roi.defined())
        roi = get_roi (src.spec());

    // Fall back to whole-image hash for only one block
    if (blocksize <= 0 || blocksize >= roi.height())
        return simplePixelHashSHA1 (src, extrainfo, roi);

    // Request for 0 threads means "use the OIIO global thread count"
    if (nthreads <= 0)
        OIIO::getattribute ("threads", nthreads);

    int nblocks = (roi.height()+blocksize-1) / blocksize;
    std::vector<std::string> results (nblocks);
    if (nthreads <= 1) {
        sha1_hasher (&src, roi, blocksize, &results[0], 0);
    } else {
        // parallel case
        boost::thread_group threads;
        int blocks_per_thread = (nblocks+nthreads-1) / nthreads;
        ROI broi = roi;
        for (int b = 0, t = 0;  b < nblocks;  b += blocks_per_thread, ++t) {
            int y = roi.ybegin + b*blocksize;
            if (y >= roi.yend)
                break;
            broi.ybegin = y;
            broi.yend = std::min (y+blocksize*blocks_per_thread, roi.yend);
            threads.add_thread (new boost::thread (sha1_hasher, &src, broi,
                                                   blocksize, &results[0], b));
        }
        threads.join_all ();
    }

#ifdef USE_OPENSSL
    // If OpenSSL was available at build time, use its SHA-1
    // implementation, which is about 20% faster than CSHA1.
    SHA_CTX sha;
    SHA1_Init (&sha);
    for (int b = 0;  b < nblocks;  ++b)
        SHA1_Update (&sha, results[b].c_str(), results[b].size());
    if (extrainfo.size())
        SHA1_Update (&sha, extrainfo.c_str(), extrainfo.size());
    unsigned char md[SHA_DIGEST_LENGTH];
    char hash_digest[2*SHA_DIGEST_LENGTH+1];
    SHA1_Final (md, &sha);
    for (int i = 0;  i < SHA_DIGEST_LENGTH;  ++i)
        sprintf (hash_digest+2*i, "%02X", (int)md[i]);
    hash_digest[2*SHA_DIGEST_LENGTH] = 0;
    return std::string (hash_digest);
#else
    // Fall back on CSHA1 if OpenSSL was not available or if 
    CSHA1 sha;
    sha.Reset ();
    for (int b = 0;  b < nblocks;  ++b)
        sha.Update ((const unsigned char *)results[b].c_str(), results[b].size());
    if (extrainfo.size())
        sha.Update ((const unsigned char *)extrainfo.c_str(), extrainfo.size());
    sha.Final ();
    std::string hash_digest;
    sha.ReportHashStl (hash_digest, CSHA1::REPORT_HEX_SHORT);
    return hash_digest;
#endif
}
예제 #17
0
OIIO_NAMESPACE_BEGIN


bool
ImageBufAlgo::IBAprep (ROI &roi, ImageBuf *dst, const ImageBuf *A,
                       const ImageBuf *B, const ImageBuf *C,
                       ImageSpec *force_spec, int prepflags)
{
    if ((A && !A->initialized()) ||
        (B && !B->initialized()) ||
        (C && !C->initialized())) {
        if (dst)
            dst->error ("Uninitialized input image");
        return false;
    }
    int maxchans = 10000;
    if (prepflags & IBAprep_CLAMP_MUTUAL_NCHANNELS) {
        // Instructions to clamp chend to the highest of the inputs
        if (dst && dst->initialized())
            maxchans = std::min (maxchans, dst->spec().nchannels);
        if (A && A->initialized())
            maxchans = std::min (maxchans, A->spec().nchannels);
        if (B && B->initialized())
            maxchans = std::min (maxchans, B->spec().nchannels);
        if (C && C->initialized())
            maxchans = std::min (maxchans, C->spec().nchannels);
    }
    if (dst->initialized()) {
        // Valid destination image.  Just need to worry about ROI.
        if (roi.defined()) {
            // Shrink-wrap ROI to the destination (including chend)
            roi = roi_intersection (roi, get_roi(dst->spec()));
        } else {
            // No ROI? Set it to all of dst's pixel window.
            roi = get_roi (dst->spec());
        }
        // If the dst is initialized but is a cached image, we'll need
        // to fully read it into allocated memory so that we're able
        // to write to it subsequently.
        dst->make_writeable (true);
    } else {
        // Not an initialized destination image!
        ASSERT ((A || roi.defined()) &&
                "ImageBufAlgo without any guess about region of interest");
        ROI full_roi;
        if (! roi.defined()) {
            // No ROI -- make it the union of the pixel regions of the inputs
            roi = A->roi();
            full_roi = A->roi_full();
            if (B) {
                roi = roi_union (roi, B->roi());
                full_roi = roi_union (full_roi, B->roi_full());
            }
            if (C) {
                roi = roi_union (roi, C->roi());
                full_roi = roi_union (full_roi, C->roi_full());
            }
        } else {
            if (A) {
                roi.chend = std::min (roi.chend, A->nchannels());
                if (! (prepflags & IBAprep_NO_COPY_ROI_FULL))
                    full_roi = A->roi_full();
            } else {
                full_roi = roi;
            }
        }
        // Now we allocate space for dst.  Give it A's spec, but adjust
        // the dimensions to match the ROI.
        ImageSpec spec;
        if (A) {
            // If there's an input image, give dst A's spec (with
            // modifications detailed below...)
            spec = force_spec ? (*force_spec) : A->spec();
            // For multiple inputs, if they aren't the same data type, punt and
            // allocate a float buffer. If the user wanted something else,
            // they should have pre-allocated dst with their desired format.
            if (B && A->spec().format != B->spec().format)
                spec.set_format (TypeDesc::FLOAT);
            if (C && (A->spec().format != C->spec().format ||
                      B->spec().format != C->spec().format))
                spec.set_format (TypeDesc::FLOAT);
            // No good can come from automatically polluting an ImageBuf
            // with some other ImageBuf's tile sizes.
            spec.tile_width = 0;
            spec.tile_height = 0;
            spec.tile_depth = 0;
        } else if (force_spec) {
            spec = *force_spec;
        } else {
            spec.set_format (TypeDesc::FLOAT);
            spec.nchannels = roi.chend;
            spec.default_channel_names ();
        }
        // Set the image dimensions based on ROI.
        set_roi (spec, roi);
        if (full_roi.defined())
            set_roi_full (spec, full_roi);
        else
            set_roi_full (spec, roi);

        if (prepflags & IBAprep_NO_COPY_METADATA)
            spec.extra_attribs.clear();
        else if (! (prepflags & IBAprep_COPY_ALL_METADATA)) {
            // Since we're altering pixels, be sure that any existing SHA
            // hash of dst's pixel values is erased.
            spec.erase_attribute ("oiio:SHA-1");
            static boost::regex regex_sha ("SHA-1=[[:xdigit:]]*[ ]*");
            std::string desc = spec.get_string_attribute ("ImageDescription");
            if (desc.size())
                spec.attribute ("ImageDescription",
                                boost::regex_replace (desc, regex_sha, ""));
        }

        dst->reset (spec);
    }
    roi.chend = std::min (roi.chend, maxchans);
    if (prepflags & IBAprep_REQUIRE_ALPHA) {
        if (dst->spec().alpha_channel < 0 ||
              (A && A->spec().alpha_channel < 0) ||
              (B && B->spec().alpha_channel < 0) ||
              (C && C->spec().alpha_channel < 0)) {
            dst->error ("images must have alpha channels");
            return false;
        }
    }
    if (prepflags & IBAprep_REQUIRE_Z) {
        if (dst->spec().z_channel < 0 ||
              (A && A->spec().z_channel < 0) ||
              (B && B->spec().z_channel < 0) ||
              (C && C->spec().z_channel < 0)) {
            dst->error ("images must have depth channels");
            return false;
        }
    }
    if (prepflags & IBAprep_REQUIRE_SAME_NCHANNELS) {
        int n = dst->spec().nchannels;
        if ((A && A->spec().nchannels != n) ||
            (B && B->spec().nchannels != n) ||
            (C && C->spec().nchannels != n)) {
            dst->error ("images must have the same number of channels");
            return false;
        }
    }
    if (prepflags & IBAprep_NO_SUPPORT_VOLUME) {
        if (dst->spec().depth > 1 ||
                (A && A->spec().depth > 1) ||
                (B && B->spec().depth > 1) ||
                (C && C->spec().depth > 1)) {
            dst->error ("volumes not supported");
            return false;
        }
    }
    if (! (prepflags & IBAprep_SUPPORT_DEEP) &&
        ((dst && dst->deep()) || (A && A->deep()) ||
         (B && B->deep()) || (C && C->deep()))) {
        dst->error ("deep data not supported");
        return false;
    }
    return true;
}
예제 #18
0
static bool
computePixelStats_ (const ImageBuf &src, ImageBufAlgo::PixelStats &stats,
                    ROI roi, int nthreads)
{
    if (! roi.defined())
        roi = get_roi (src.spec());
    else
        roi.chend = std::min (roi.chend, src.nchannels());

    int nchannels = src.spec().nchannels;

    // Use local storage for smaller batches, then merge the batches
    // into the final results.  This preserves precision for large
    // images, where the running total may be too big to incorporate the
    // contributions of individual pixel values without losing
    // precision.
    //
    // This approach works best when the batch size is the sqrt of
    // numpixels, which makes the num batches roughly equal to the
    // number of pixels / batch.
    ImageBufAlgo::PixelStats tmp;
    reset (tmp, nchannels);
    reset (stats, nchannels);
    
    int PIXELS_PER_BATCH = std::max (1024,
            static_cast<int>(sqrt((double)src.spec().image_pixels())));
    
    if (src.deep()) {
        // Loop over all pixels ...
        for (ImageBuf::ConstIterator<T> s(src, roi); ! s.done();  ++s) {
            int samples = s.deep_samples();
            if (! samples)
                continue;
            for (int c = roi.chbegin;  c < roi.chend;  ++c) {
                for (int i = 0;  i < samples;  ++i) {
                    float value = s.deep_value (c, i);
                    val (tmp, c, value);
                    if ((tmp.finitecount[c] % PIXELS_PER_BATCH) == 0) {
                        merge (stats, tmp);
                        reset (tmp, nchannels);
                    }
                }
            }
        }
    } else {  // Non-deep case
        // Loop over all pixels ...
        for (ImageBuf::ConstIterator<T> s(src, roi); ! s.done();  ++s) {
            for (int c = roi.chbegin;  c < roi.chend;  ++c) {
                float value = s[c];
                val (tmp, c, value);
                if ((tmp.finitecount[c] % PIXELS_PER_BATCH) == 0) {
                    merge (stats, tmp);
                    reset (tmp, nchannels);
                }
            }
        }
    }

    // Merge anything left over
    merge (stats, tmp);

    // Compute final results
    finalize (stats);

    return ! src.has_error();
};
예제 #19
0
void Predator::initialLearning()
{
    //this->detectedBB = this->detector->detect(this->currImg, this->integralImg);
    Mat target = get_roi(this->currImg,this->currBB);
    this->objModel.label = this->label;
    this->objModel.load(target);
    this->detector->featureTracker->init(this->objModel);

    NormalizedPatch patch = this->currBB.extractNormalizedPatch(this->currImg);
    patch.positive = 1;

    float initVar = patch.var();//this->detector->varianceFilter->computeVar(this->integralImg,this->integralImgSqr, this->currBB);
    detector->varianceFilter->minVar = initVar/3.0;


    float overlaps[this->detector->windows.size()];
    this->currBB.overlap(this->detector->windows, overlaps);

    //Add all bounding boxes with high overlap

    vector< pair<int,float> > positiveIndices;
    vector<int> negativeIndices;

    //First: Find overlapping positive and negative patches

    for(int i = 0; i < this->detector->windows.size(); i++)
    {

        if(overlaps[i] > 0.6f)
        {
            positiveIndices.push_back(pair<int,float>(i,overlaps[i]));
        }

        if(overlaps[i] < 0.1f)
        {
            negativeIndices.push_back(i);
        }
    }


    sort(positiveIndices.begin(), positiveIndices.end(), tldSortByOverlapDesc);

    vector<NormalizedPatch> patches;

    patches.push_back(patch); //Add first patch to patch list

    int numIterations = std::min<size_t>(positiveIndices.size(), 10); //Take at most 10 bounding boxes (sorted by overlap)
    for(int i = 0; i < numIterations; i++)
    {
        int idx = positiveIndices.at(i).first;
        //Learn this bounding box
        //TODO: Somewhere here image warping might be possible
        this->detector->ffClassifier->train(this->integralImg, this->detector->windows[idx], true);
    }

    srand(time(NULL)); //TODO: This is not guaranteed to affect random_shuffle

    random_shuffle(negativeIndices.begin(), negativeIndices.end());

    //Choose 100 random patches for negative examples
    for(size_t i = 0; i < std::min<size_t>(100,negativeIndices.size()); i++)
    {
        int idx = negativeIndices.at(i);

        NormalizedPatch patch = this->detector->windows[idx].extractNormalizedPatch(this->currImg);
        patch.positive = 0;
        patches.push_back( patch );
    }

    this->detector->nnClassifier->learn(patches);



}