Κεφάλαιο 6 Λογισμικό εντοπισμού αντικειμένων
6.11 Αρχιτεκτονική
87
88
tr1,System::Windows::Forms::TrackBar^ tr2,System::Windows::Forms::TrackBar^
tr3,System::Windows::Forms::TrackBar^ tr4 ) { msclr::interop::marshal_context cxt;
IplImage *frame;
frame = cvLoadImage( cxt.marshal_as<char const*>(a), 1 );
int num_of_results = -1;
int objcounter = 0;
CvFont font;
int thresh1=DEFAULT_TRACKBAR_VAL, thresh2=DEFAULT_TRACKBAR_VAL;
IplImage *small_image = cvCreateImage(cvSize((frame->width),(frame-
>height)),IPL_DEPTH_8U,3);
IplImage *small_grey_image = cvCreateImage(cvGetSize(small_image), IPL_DEPTH_8U, 1);
IplImage *edge_image = cvCreateImage(cvGetSize(small_image), IPL_DEPTH_8U, 1);
CvMemStorage *storage = cvCreateMemStorage(0);
cvThreshold( small_grey_image, small_grey_image, tr3->Value, 255, CV_THRESH_OTSU );
CvSeq *contours = 0;
cvResize(frame, small_image, /*CV_INTER_LINEAR*/CV_INTER_CUBIC);
cvCvtColor(small_image, small_grey_image, CV_RGB2GRAY);
cvShowImage("Gray-Scale", small_grey_image);
cvCanny(small_grey_image, edge_image, (double)tr3->Value, (double)tr3->Value, 3);
cvDilate(edge_image, small_grey_image, 0, 1);
num_of_results = cvFindContours(small_grey_image, storage, &contours, sizeof(CvContour), CV_RETR_CCOMP,
/*CV_CHAIN_APPROX_NONE*/CV_CHAIN_APPROX_TC89_KCOS, cvPoint(0,0));
cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.7, 0.7, 0, 1, CV_AA);
textBox1->Text = textBox1->Text + "Αποτελέσματα για την εικόνα:"+a-
>ToString()+"\r\n";
ofstream f("results.xml");
XmlStream xml(f);
xml << prolog();
xml << tag("results");
ofstream myfile;
/*myfile.open ("results2.xml");
myfile << "<?xml version=\"1.0\"?>";
myfile << "<results>";*/
for( ; contours != 0; contours = contours->h_next ) {
//System::Windows::Forms::MessageBox::Show(contours->storage->);
CvRect box = cvBoundingRect(contours,1);
CvScalar color = CV_RGB( rand()&255, rand()&255, rand()&255 );
/* replace CV_FILLED with 1 to see the outlines */
//cvDrawContours( small_image, contours, color, color, -1, CV_AA, 1 );
if( ((contours->total)>tr1->Value) && ((fabs(cvContourArea( contours, CV_WHOLE_SEQ )))>tr2->Value) ) {
cvDrawContours(small_image, contours, color, color, tr4->Value, 1, CV_AA, cvPoint(0,0));
cvPutText(small_image, cxt.marshal_as<char
const*>(objcounter.ToString()), cvPoint(box.x+10,box.y+10), &font, cvScalar(255, 255, 0, 0));
textBox1->Text = textBox1->Text + "Σχήμα" + objcounter.ToString() +
":\r\n";
if(this->a->Equals("Παραλληλόγραμμο")) {
89
cvRectangle(small_image,cvPoint(box.x,box.y),cvPoint(box.x+box.width,box.y+box.he ight),color,1,CV_AA,0);
} else if (this->a->Equals("Κύκλος")) {
cvCircle(small_image,cvPoint((box.x+(box.width/2)),(box.y+(box.height/2))),box.wi dth,color,1,CV_AA,0);
} else {
System::Windows::Forms::MessageBox::Show("Δεν έχετε επιλέξει πρότυπο σχήμα");
return;
}
if(this->perifereia) {
textBox1->Text = textBox1->Text +
"Περίμετρος:"+fabs(cvContourPerimeter(contours)).ToString() +"\r\n";
}
if(this->emvado) {
textBox1->Text = textBox1->Text + "Εμβαδό:"+fabs(cvContourArea(
contours, CV_WHOLE_SEQ )).ToString() +"\r\n";
}
if(this->geom_center) {
textBox1->Text = textBox1->Text +
"Kέντρο(pixels):("+(box.x+(box.width/2)).ToString()+","+(box.y+(box.height/2)).To String()+")"+"\r\n";
}
if(this->geom_mikos) {
textBox1->Text = textBox1->Text + "Γεωμετρικό Μήκος:"+box.width.ToString()+"\r\n";
}
if(this->geom_platos) {
textBox1->Text = textBox1->Text + "Γεωμετρικό Πλάτος:"+box.height.ToString()+"\r\n";
}
objcounter = objcounter+1;
xml << tag("shape");
xml << attr("id") << cxt.marshal_as<char const*>(objcounter.ToString());
xml << tag("source_image");
xml << chardata() << cxt.marshal_as<char const*>(a);
xml << endtag();
xml << tag("processed_image");
xml << chardata() << "output.jpg";
xml << endtag();
xml << tag("perimeter");
xml << chardata() << cxt.marshal_as<char const*>(fabs(cvContourPerimeter(contours)).ToString());
xml << endtag();
xml << tag("area");
90
xml << chardata() << cxt.marshal_as<char const*>(fabs(cvContourArea(
contours, CV_WHOLE_SEQ )).ToString());
xml << endtag();
xml << tag("center");
xml << chardata() << cxt.marshal_as<char
const*>((box.x+(box.width/2)).ToString()+","+(box.y+(box.height/2)).ToString());
xml << endtag();
xml << tag("geom_length");
xml << chardata() << cxt.marshal_as<char const*>(box.width.ToString());
xml << endtag();
xml << tag("geom_width");
xml << chardata() << cxt.marshal_as<char const*>(box.height.ToString());
xml << endtag();
xml << endtag("shape");
} }
if(num_of_results == -1) {
System::Windows::Forms::MessageBox::Show("Δεν βρέθηκαν αναγνωρίσιμα αντικείμενα εντός της εικόνας.");
} else {
System::Windows::Forms::MessageBox::Show("Αναγνωρίστηκαν
"+num_of_results.ToString()+" αντικείμενα.\r\nΑγνοήθηκαν "+(num_of_results - objcounter).ToString()+" σαν εξαιρετικά μικρά.");
}
//Finally, display the image in the window.
cvShowImage(cxt.marshal_as<char const*>(a), small_image);
cvShowImage("Edge-Scale", small_grey_image);
cvSaveImage("output.jpg",small_image);
//return rs1;
}
Το τρίτο είναι το module «Image Retrieval» που αφορά τις μεθόδους λήψης και αποθήκευσης εικόνας, είτε από το υπολογιστικό σύστημα είτε, το κυριότερο, από συσκευές λήψης. Υλοποιείται από τις κλάσεις Form1, Imcap και Imcapwiz. Για την λήψη, προβολή και αποθήκευση της εικόνας χρησιμοποιούνται από κοινού μέθοδοι του OpenCV και δευτερευόντως μέθοδοι της Visual C++
.NET, έτσι ώστε να εξασφαλίζεται η συμβατότητα με την πλατφόρμα του λειτουργικού συστήματος Windows. Στο παρακάτω πλαίσιο, παρατίθεται η OpenCV μέθοδος λήψης και προβολής εικόνας που λαμβάνεται απευθείας από μια βιντεοκάμερα.
CvCapture* capture = cvCaptureFromCAM( CV_CAP_ANY );
91
cvNamedWindow( "Λήψη Εικόνας", CV_WINDOW_AUTOSIZE );
int p[3];
IplImage* frame;
// Show the image captured from the camera in the window and repeat
while ( 1 ) {
// Get one frame
frame = cvQueryFrame( capture );
if ( !frame ) {
System::Windows::Forms::MessageBox::Show("Το frame είναι κενό");
getchar();
break;
}
cvShowImage( "Λήψη Εικόνας", frame );
if ( (cvWaitKey(10) & 255) == 27 ) { break;
} }
p[0] = CV_IMWRITE_JPEG_QUALITY;
p[1] = 10;
p[2] = 0;
Στο παρακάτω πλαίσιο φαίνεται η μέθοδος αποθήκευσης μιας εικόνας στο μέσο αποθήκευσης του υπολογιστικού συστήματος – host.
saveFileDialog1->Filter::set("Image files (*.jpg)|*.jpg|All files (*.*)|*.*");
saveFileDialog1->ShowDialog();
if(!saveFileDialog1->CheckFileExists) {
using namespace Runtime::InteropServices;
const char* chars = (const
char*)(Marshal::StringToHGlobalAnsi(saveFileDialog1->FileName)).ToPointer();
//std::string& os = chars;
cvSaveImage(chars, frame, p);
Marshal::FreeHGlobal(IntPtr((void*)chars));
this->path2img = saveFileDialog1->FileName;
}
Το τέταρτο είναι το module «SETUP» που αφορά το σενάριο παραγωγής του προγράμματος εγκατάστασης. Πρόκειται για ένα πολυπληθές σύνολο από scripts του λογισμικού Inno Setup [24].
Η εκτέλεσή τους, προϋποθέτει την ύπαρξη του Inno Setup runtime και έχει σαν αποτέλεσμα την
παραγωγή του προγράμματος εγκατάστασης, του οποίου η λειτουργία περιγράφηκε σε προηγούμενη
ενότητα. Στο παρακάτω απόσπασμα παρατίθεται ένα ενδεικτικό σενάριο που υλοποιεί τη
μεταφόρτωση και εγκατάσταση του .NET 3.5 runtime environment.
92
// requires Windows Server 2003 Service Pack 1, Windows Server 2008, Windows Vista, Windows XP Service Pack 2
// requires Windows Installer 3.1
// WARNING: express setup (downloads and installs the components depending on your OS) if you want to deploy it on cd or network download the full bootsrapper on website below
// http://www.microsoft.com/downloads/details.aspx?FamilyId=333325FD-AE52-4E35- B531-508D977D32A6
[CustomMessages]
dotnetfx35_title=.NET Framework 3.5 dotnetfx35_size=3 MB - 197 MB
[Code]
const
dotnetfx35_url = 'http://download.microsoft.com/download/7/0/3/703455ee- a747-4cc8-bd3e-98a615c3aedb/dotNetFx35setup.exe';
procedure dotnetfx35();
begin
if (netfxinstalled(NetFx35, '') = false) then
AddProduct('dotnetfx35' + GetArchitectureString() + '.exe', '/lang:enu /passive /norestart',
CustomMessage('dotnetfx35_title'), CustomMessage('dotnetfx35_size'), dotnetfx35_url,
false, false);
end;