/*! \fn FaceDetectorPlugin::checkZone(Zone *zone, const Image *zmImage)
 *  \param zone is a zone where faces will be detected
 *  \param zmImage is an image to perform face detection (in the form of ZM' Image)
 *  \return true if there were objects detected in given image and
 *          false otherwise
 */
bool FaceDetectorPlugin::checkZone(Zone *zone, const Image *zmImage)
{
    //log(LOG_DEBUG, "Entering checkZone.");
    double score;
    Polygon zone_polygon = Polygon(zone->GetPolygon()); // Polygon of interest of the processed zone.
    //char szMessage[50];
    //sprintf(szMessage, "Polygon of the zone has %d vertices.", zone_polygon.getNumCoords());
    //log(LOG_WARNING, szMessage);

	//zone->ResetStats();

    /*
    log(LOG_WARNING, "precheck");
    if ( !zone->CheckOverloadCount() )
    {
        log(LOG_WARNING, "CheckOverloadCount() return false, we'll return false.");
        return(false);
    }
    */
    //zmLoadConfig();
    // An image for highlighting detected objects.                                
    Image *pMaskImage = new Image(zmImage->Width(), zmImage->Height(), ZM_COLOUR_GRAY8, ZM_SUBPIX_ORDER_NONE );
    pMaskImage->Fill(BLACK);

    //log(LOG_WARNING, "FILLBLACK.");
    // An temporary image in the form of ZM for making from it CvMat.
    // If don't use temp image, after rgb->bgr it will change.
    Image *tempZmImage = new Image(*zmImage);
    CvMat* cvInputImage = NULL;
    CvMat* pScaledImage = NULL;

    bool bDoResizing = (m_fImageScaleFactor != 1.0);    // resize image or not

    if (tempZmImage->Colours() == ZM_COLOUR_GRAY8)
    {
        // if image is not colored, create an one-channel CvMat.
        cvInputImage = cvCreateMat(tempZmImage->Height(), tempZmImage->Width(), CV_8UC1);
        unsigned char *buffer = (unsigned char*)tempZmImage->Buffer();
        cvSetData(cvInputImage, buffer, tempZmImage->Width());
    }
    // NEXTIME XXX TODO: manage also 32 bit images!
    else
    {
        // otherwise create a three-channel CvMat and then convert colors from RGB to BGR.
        cvInputImage = cvCreateMat(tempZmImage->Height(), tempZmImage->Width(), CV_8UC3);
        unsigned char *buffer = (unsigned char*)tempZmImage->Buffer();
        cvSetData(cvInputImage, buffer, tempZmImage->Width() * 3);
        cvCvtColor(cvInputImage, cvInputImage, CV_RGB2BGR);
    }

    if (bDoResizing)
    {
        int nNewWidth = int (m_fImageScaleFactor * zmImage->Width());
        int nNewHeight = int (m_fImageScaleFactor * tempZmImage->Height());
        int nImageElemType = cvGetElemType(cvInputImage);
        pScaledImage = cvCreateMat(nNewHeight, nNewWidth, nImageElemType);
        cvResize(cvInputImage, pScaledImage, CV_INTER_LINEAR);
    }


    //Process image

    vector<CvRect> foundObjects;
    if (bDoResizing)
        foundObjects = _opencvHaarDetect(pScaledImage);
    else
        foundObjects = _opencvHaarDetect(cvInputImage);

    if (foundObjects.size() > 0)
        log(LOG_INFO, "OBJECTS WERE DETECTED");

    score = 0;
    for (vector<CvRect>::iterator it = foundObjects.begin(); it < foundObjects.end(); it++)
    {
        // Process found objects.

        // Scale object's coordinates back if image has been scaled.
        int x1 = int(it->x/m_fImageScaleFactor), x2 = int((it->x + it->width)/m_fImageScaleFactor), y1 = int(it->y/m_fImageScaleFactor), y2 = int((it->y + it->height)/m_fImageScaleFactor);
        
        // Check if object's rectangle is inside zone's polygon of interest.
        Coord rectVertCoords[4] = {Coord(x1, y1), Coord(x1, y2), Coord(x2, y1), Coord(x2, y2)};
        int nNumVertInside = 0;
        for (int i = 0; i < 4; i++)
        {
            nNumVertInside += zone_polygon.isInside(rectVertCoords[i]);
        }
        if (nNumVertInside < 3)
        // if at least three rectangle coordinates are inside polygon, consider rectangle as belonging to the zone
        // otherwise process next object
            continue;

        // Fill a box with object in the mask
        Box *faceBox = new Box(x1, y1, x2, y2);
        pMaskImage->Fill(WHITE, faceBox);
        // Calculate score as portion of object area in the image
        score += (100.0*(it->width)*(it->height)/m_fImageScaleFactor/m_fImageScaleFactor)/zone_polygon.Area();
        delete faceBox;
    }


    if (score == 0)
    {
        //log(LOG_DEBUG, "No objects found. Exit.");
        delete pMaskImage;
        delete tempZmImage;

        if (cvInputImage)
            cvReleaseMat(&cvInputImage);
        if (pScaledImage)
            cvReleaseMat(&pScaledImage);

        return( false );
    }



    if ( m_fMinAlarmScore && ( score < m_fMinAlarmScore) )
    {
        delete pMaskImage;
        delete tempZmImage;

        if (cvInputImage)
            cvReleaseMat(&cvInputImage);
        if (pScaledImage)
            cvReleaseMat(&pScaledImage);

        return( false );
    }
    if ( m_fMaxAlarmScore && (score > m_fMaxAlarmScore) )
    {
        zone->SetOverloadCount(zone->GetOverloadFrames());
        delete pMaskImage;
        delete tempZmImage;

        if (cvInputImage)
            cvReleaseMat(&cvInputImage);
        if (pScaledImage)
            cvReleaseMat(&pScaledImage);

        return( false );
    }


    zone->SetScore(max(1, (int)score));

    //Get mask by highlighting contours of objects and overlaying them with previous contours.
    Rgb alarm_colour = RGB_GREEN;
	Image *hlZmImage = pMaskImage->HighlightEdges(alarm_colour, ZM_COLOUR_RGB24, 
                                                 ZM_SUBPIX_ORDER_RGB, &zone_polygon.Extent());

    if (zone->Alarmed())
    {
        // if there were previous detection and they have already set up alarm image
        // then overlay it with current mask
        Image* pPrevZoneMask = new Image(*(zone->AlarmImage()));
        pPrevZoneMask->Overlay(*hlZmImage);
        zone->SetAlarmImage(pPrevZoneMask);
        delete pPrevZoneMask;
    }
    else
        zone->SetAlarmImage(hlZmImage);

    delete pMaskImage;
    delete hlZmImage;
    delete tempZmImage;

    if (cvInputImage)
        cvReleaseMat(&cvInputImage);
    if (pScaledImage)
        cvReleaseMat(&pScaledImage);

    //log(LOG_DEBUG, "Leaving checkZone.");
    return true;
}
Beispiel #2
0
/*! \fn ANPRPlugin::checkZone(Zone *zone, const Image *zmImage)
 *  \param zone is a zone where faces will be detected
 *  \param zmImage is an image to perform face detection (in the form of ZM' Image)
 *  \return true if there were objects detected in given image and
 *          false otherwise
 */
bool ANPRPlugin::checkZone(Zone *zone, const Image *zmImage)
{
   
    double score;
    Polygon zone_polygon = Polygon(zone->GetPolygon()); // Polygon of interest of the processed zone.

    Image *pMaskImage = new Image(zmImage->Width(), zmImage->Height(), ZM_COLOUR_GRAY8, ZM_SUBPIX_ORDER_NONE );
    pMaskImage->Fill(BLACK);
    // An temporary image in the form of ZM for making from it CvMat.
    // If don't use temp image, after rgb->bgr it will change.
    Image *tempZmImage = new Image(*zmImage);
    int imgtype=CV_8UC1;
    if (tempZmImage->Colours() == ZM_COLOUR_RGB24)
      imgtype=CV_8UC3;
    Mat cvInputImage = Mat(
                           tempZmImage->Height(),
                           tempZmImage->Width(),
                           imgtype, (unsigned char*)tempZmImage->Buffer()).clone();
    //Mat cvInputImage = cvtmpInputImage.reshape(0, tempZmImage->Colours());
    //Mat cvInputImage = cvtmpInputImage.reshape(0, tempZmImage->Height());
    if (tempZmImage->Colours() == ZM_COLOUR_RGB24)
    {
      cvtColor(cvInputImage, cvInputImage, CV_RGB2BGR);
    }
    //imwrite("/tmp/sarca.jpg", cvInputImage);
    //Process image
    liprec::LiPRec plateDetector;
    liprec::PlatesImage plates;
    plateDetector.detectPlates(cvInputImage, &plates);
    score = 0;
    if(plates.plates.size() > 0) {
      log(LOG_INFO, "PLATES WERE DETECTED");
      for(unsigned int i=0;i<plates.plates.size();i++) {

        // Check if object's rectangle is inside zone's polygon of interest.
        int x1 = plates.plates[i].rect.x, x2 = int(plates.plates[i].rect.x+plates.plates[i].rect.width);
        int y1 = plates.plates[i].rect.y, y2 = int(plates.plates[i].rect.y+plates.plates[i].rect.height);
        Coord rectVertCoords[4] = {Coord(x1, y1), Coord(x1, y2), Coord(x2, y1), Coord(x2, y2)};
        int nNumVertInside = 0;
        for (int p = 0; p < 4; p++)
        {
            nNumVertInside += zone_polygon.isInside(rectVertCoords[p]);
        }
        if (nNumVertInside < 3)
        // if at least three rectangle coordinates are inside polygon, 
        // consider rectangle as belonging to the zone
        // otherwise process next object
            continue;
        log(LOG_INFO, plates.plates[i].platetxt);
        // Fill a box with object in the mask
        Box *plateBox = new Box(x1, y1, x2, y2);
        pMaskImage->Fill(WHITE, plateBox);
        score=m_nAlarmScore;
        delete plateBox;
      }
    }


    if (score == 0)
    {
        //log(LOG_DEBUG, "No objects found. Exit.");
        delete pMaskImage;
        delete tempZmImage;

        // XXX We need to delete Mats?

        return( false );
    }
    /*
    else
    {
        zone->SetOverloadCount(zone->GetOverloadFrames());
        delete pMaskImage;
        delete tempZmImage;

        return( false );
    }*/


    zone->SetScore((int)score);

    //Get mask by highlighting contours of objects and overlaying them with previous contours.
    Rgb alarm_colour = RGB_GREEN;
	 Image *hlZmImage = pMaskImage->HighlightEdges(alarm_colour, ZM_COLOUR_RGB24, 
                                                 ZM_SUBPIX_ORDER_RGB, &zone_polygon.Extent());

    if (zone->Alarmed())
    {
        // if there were previous detection and they have already set up alarm image
        // then overlay it with current mask
        Image* pPrevZoneMask = new Image(*(zone->AlarmImage()));
        pPrevZoneMask->Overlay(*hlZmImage);
        zone->SetAlarmImage(pPrevZoneMask);
        delete pPrevZoneMask;
    }
    else
        zone->SetAlarmImage(hlZmImage);

    delete pMaskImage;
    delete hlZmImage;
    delete tempZmImage;

    return true;
}