/*********************************************************************** This file is part of libzm_anpr_plugin, License Plate REcognition. Copyright (C) 2012 Franco (nextime) Lanza LiPRec is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. LiPRec is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with LiPRec. If not, see . ************************************************************************/ #define LIST LIPREC_LIST // This is a workaround to avoid the conflict #include // of typedef LIST in both mysql and tesseract headers... //#include "opencv2/highgui/highgui.hpp" #undef LIST #include "anpr_plugin.h" //! Retrieve the engine version we're going to expect extern "C" int getEngineVersion() { return ZM_ENGINE_VERSION; } //! Tells us to register our functionality to an engine kernel extern "C" void registerPlugin(PluginManager &PlM, string sPluginName) { PlM.getImageAnalyser().addDetector( auto_ptr(new ANPRPlugin(sPluginName)) ); } using namespace cv; //using namespace liprec; ANPRPlugin::ANPRPlugin() : Detector(), m_nMinObjSize(DEFAULT_DETECTOR_MIN_OBJECT_SIZE), m_nMaxObjSize(DEFAULT_DETECTOR_MAX_OBJECT_SIZE) { m_sDetectionCause = DETECTED_CAUSE; m_sLogPrefix = LOG_PREFIX; log(LOG_NOTICE, "License Plate Recognition Plugin\'s Object has been created."); } ANPRPlugin::ANPRPlugin(string sPluginName) : Detector(sPluginName), m_nMinObjSize(DEFAULT_DETECTOR_MIN_OBJECT_SIZE), m_nMaxObjSize(DEFAULT_DETECTOR_MAX_OBJECT_SIZE) { m_sDetectionCause = DETECTED_CAUSE; m_sLogPrefix = LOG_PREFIX; log(LOG_NOTICE, "License Plate Recognition Plugin\'s Object has been created."); } /*! \fn ANPRPlugin::loadConfig(string sConfigFileName) * \param sConfigFileName is path to configuration to load parameters from */ void ANPRPlugin::loadConfig(string sConfigFileName) { options_description config_file("Configuration file options."); variables_map vm; config_file.add_options() ((m_sConfigSectionName + string(".min-obj-size")).c_str(), value()->default_value(DEFAULT_DETECTOR_MIN_OBJECT_SIZE)) ((m_sConfigSectionName + string(".max-obj-size")).c_str(), value()->default_value(DEFAULT_DETECTOR_MAX_OBJECT_SIZE)) ((m_sConfigSectionName + string(".alarm-score")).c_str(), value()->default_value(DEFAULT_ALARM_SCORE)) ((m_sConfigSectionName + string(".det-cause")).c_str(), value()->default_value(DETECTED_CAUSE)) ((m_sConfigSectionName + string(".log-prefix")).c_str(), value()->default_value(LOG_PREFIX)) ; ifstream ifs(sConfigFileName.c_str()); store(parse_config_file(ifs, config_file, true), vm); notify(vm); m_nMinObjSize = vm[(m_sConfigSectionName + string(".min-obj-size")).c_str()].as(); m_nMaxObjSize = vm[(m_sConfigSectionName + string(".max-obj-size")).c_str()].as(); m_nAlarmScore = vm[(m_sConfigSectionName + string(".alarm-score")).c_str()].as(); m_sDetectionCause = vm[(m_sConfigSectionName + string(".det-cause")).c_str()].as(); m_sLogPrefix = vm[(m_sConfigSectionName + string(".log-prefix")).c_str()].as(); zmLoadConfig(); log(LOG_NOTICE, "License Plate Recognition Plugin\'s Object is configured."); } ANPRPlugin::~ANPRPlugin() { } /*! \fn ANPRPlugin::ANPRPlugin(const ANPRPlugin& source) * \param source is the object for copying */ ANPRPlugin::ANPRPlugin(const ANPRPlugin& source) : Detector(source), m_nMinObjSize(source.m_nMinObjSize), m_nMaxObjSize(source.m_nMaxObjSize) { } /*! \fn ANPRPlugin:: operator=(const ANPRPlugin& source) * \param source is the object for copying */ ANPRPlugin & ANPRPlugin:: operator=(const ANPRPlugin& source) { Detector::operator=(source); m_nMinObjSize = source.m_nMinObjSize; m_nMaxObjSize = source.m_nMaxObjSize; return *this; } /*! \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;iFill(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; }