Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder A1 Listado de programas de C++ Builder A1.1 Código fuente principal VisionV7.cpp //--------------------------------------------------------------------------#include <vcl.h> #pragma hdrstop //--------------------------------------------------------------------------USEFORM("Unit1_VisionV7.cpp", Form1); //--------------------------------------------------------------------------int invierte(SAFEARRAY* psaimagenIN,SAFEARRAY* psaimagenOUT,int anchopix); WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { try { Application->Initialize(); Application->CreateForm(__classid(TForm1), &Form1); Application->Run(); } catch (Exception &exception) { Application->ShowException(&exception); } catch (...) { try { throw Exception(""); } catch (Exception &exception) { Application->ShowException(&exception); } } return 0; } //--------------------------------------------------------------------------- A1.2 Código fuente Unit1_VisionV7.cpp //--------------------------------------------------------------------------#include <vcl.h> #pragma hdrstop #include "Unit1_VisionV7.h" //--------------------------------------------------------------------------#pragma package(smart_init) Ingeniería en Automática y Electrónica Industrial A1-1 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder #pragma link "MIL_OCX" #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------#define ValorBinarioBajo 0 #define ValorBinarioAlto 255 #define NivelesGris 256 #define UmbralOtsuMinimo 20 // Minimo umbral automatico admitido #define TimeoutTCP 500 // ms #define MaximoEtiquetas 500 // Limite de etiquetas en barrido etiquetado #define MaximoClases 50 // Maximo-1 objetos distintos en etiquetado #define AnchoPeriferia 10 // Ancho considerado de la periferia, en pixeles #define MaxPixPeriferia 100 // Maximo de pixeles permitidos en periferia #define PixToMm 0.650 // Factor de conversión de pixeles a mm #define MinPequeno 1300 // Número de pixeles mínimo para círculo pequeño #define MaxPequeno 1800 // Número de pixeles máximo para círculo pequeño #define MinGrande 2750 // Número de pixeles mínimo para círculo grande #define MaxGrande 3250 // Número de pixeles máximo para círculo grande #define OrdenDeMascara 3 // Orden IMPAR de matriz de máscara en Erosión #define OrdenDeMascaraMediana 3 // Orden IMPAR de mascara en filtrado mediana //--------------------------------------------------------------------------/* Variables test,son réplicas globales de variables locales, para permitir acceso al debugger cuando se pausa la aplicación. Pueden verse con Watch */ double histogramatest[NivelesGris],vectoromegatest[NivelesGris]; double vectorsigmabsquaredtest[NivelesGris]; int PixSizetest; int enlacestest[MaximoEtiquetas],clasestest[MaximoEtiquetas]; int etiquetas[640][480]; //double histograma[NivelesGris],vectoromega[NivelesGris]; int EtiquetaMaximatest,ClaseMaximatest; int cnt[10],cntsolapamientos,cntsolapamientos1ciclo; //--------------------------------------------------------------------------enum Estado {Alarma,Preparado,MarchaContinuoEsperando,MarchaContinuoEnProceso, Marcha1CicloEnProceso}; class Global { private: static static static static static static public: static static static static static static static static static static static static }; int XCG[MaximoClases]; int YCG[MaximoClases]; int TipoPieza[MaximoClases]; int Npiezas; enum Estado EstadoAuto; int Nciclos; void SetXCG(int n,int newXCG) { int GetXCG(int n) { void SetYCG(int n,int newYCG) { int GetYCG(int n) { void SetNpiezas(int newNpiezas) { int GetNpiezas() { void NuevoEstado(Estado newEstado) void Para() { enum Estado GetEstado() { void SetNCiclos(int newNciclos) { void IncNciclos() { int GetNciclos() { Ingeniería en Automática y Electrónica Industrial XCG[n]=newXCG; } return XCG[n]; } YCG[n]=newYCG; } return YCG[n]; } Npiezas=newNpiezas; } return Npiezas; } { EstadoAuto=newEstado; } EstadoAuto=Preparado; } return EstadoAuto; } Nciclos=newNciclos; } Nciclos++; } return Nciclos; } A1-2 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder int Global::XCG[MaximoClases]; int Global::YCG[MaximoClases]; int Global::TipoPieza[MaximoClases]; int Global::Npiezas; enum Estado Global::EstadoAuto; int Global::Nciclos; //--------------------------------------------------------------------------//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonGrabClick(TObject *Sender) { ActionCaptura->Execute(); } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonGrabContClick(TObject *Sender) { Digitizer1->GrabContinuous(); // Graba sobre Imagemil1 } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonHaltClick(TObject *Sender) { Digitizer1->Halt(); } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonCopiaClick(TObject *Sender) { //vimagen.parray=Global::Getpsaimagen1(); //ImageMil2->Put(vimagen,imSingleBand,imAllBands,0,0,SizeX,SizeY); } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonInvertClick(TObject *Sender) { //invierte(Global::Getpsaimagen2(),Global::Getpsaimagen2(),255); //vimagen.parray=Global::Getpsaimagen2(); //ImageMil2->Put(vimagen,imSingleBand,imAllBands,0,0,SizeX,SizeY); } //--------------------------------------------------------------------------void __fastcall TForm1::ScrollBarUmbralChange(TObject *Sender) { StaticTextUmbral->Caption=AnsiString(ScrollBarUmbral->Position); } //--------------------------------------------------------------------------void __fastcall TForm1::FormCreate(TObject *Sender) Ingeniería en Automática y Electrónica Industrial A1-3 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder { StaticTextUmbral->Caption=AnsiString(ScrollBarUmbral->Position); /* Al crear el SAFEARRAY se invierten los componentes de rgsabound porque el SAFEARRAY almacena los datos por columnas (tipo BASIC o FORTRAN) en lugar de por filas como C++. Así el compilador garantiza que los direccionamientos [i][j] van a funcionar correstamente. Creo. ShowMessage( "Tras SafeArrayCreate SizeX= "+AnsiString(SizeX)+"\n" "psaimagen1->rgsabound[0].cElements= "+ AnsiString(psaimagen1->rgsabound[0].cElements)+"\n" "SizeY= "+AnsiString(SizeY)+"\n" "psaimagen1->rgsabound[0].cElements= " + AnsiString(psaimagen1->rgsabound[1].cElements)+"\n" ); */ Global::NuevoEstado(Preparado); StatusBarInfo->Panels->Items[1]->Text= "ESTADO AUTO: Preparado"; StatusBarInfo->Panels->Items[2]->Text="TCP SERVER ROBOT: pendiente"; SpeedButtonAuto->Click(); /* Tamaño de imagen en función del escalado de Digitizer */ ImageMil1->SizeX=static_cast<long>(640*Digitizer1->ScaleX); ImageMil1->SizeY=static_cast<long>(480*Digitizer1->ScaleY); ImageMil2->SizeX=ImageMil1->SizeX; ImageMil2->SizeY=ImageMil1->SizeY; } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonBinarizaClick(TObject *Sender) { ActionBinariza->Execute(); } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonExitClick(TObject *Sender) { ImageMil1->Free(); ImageMil2->Free(); Digitizer1->Free(); SYSTEM1->Free(); exit(0); } //--------------------------------------------------------------------------void __fastcall TForm1::ImageMil1ContentModified(TObject *Sender, long OffsetX, long OffsetY, long SizeX, long SizeY) { ShowMessage("Evento Imagen 1 modificada"); } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonHistogramaClick(TObject *Sender) Ingeniería en Automática y Electrónica Industrial A1-4 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder { ActionHistograma->Execute(); ButtonHistograma->SetFocus(); // Para no repetir en modo paso a paso } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonCGClick(TObject *Sender) { ActionBusqueda->Execute(); } //--------------------------------------------------------------------------void __fastcall TForm1::IdTCPClient1Connected(TObject *Sender) { StatusBarInfo->Panels->Items[2]->Text="TCP SERVER ROBOT: CONECTADO"; } //--------------------------------------------------------------------------void __fastcall TForm1::IdTCPClient1Disconnected(TObject *Sender) { StatusBarInfo->Panels->Items[2]->Text="TCP SERVER ROBOT: DESCONECTADO"; CheckBoxComunicate->Checked=FALSE; } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonConnectClick(TObject *Sender) { if(! IdTCPClient1->Connected()) IdTCPClient1->Connect(); } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonDisconnectClick(TObject *Sender) { if(IdTCPClient1->Connected()) IdTCPClient1->Disconnect(); } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonWriteClick(TObject *Sender) { AnsiString XCGstring,YCGstring; if(IdTCPClient1->Connected()) { XCGstring=AnsiString(Global::GetXCG(0)); XCGstring=AnsiString(Global::GetXCG(0)); IdTCPClient1->WriteLn(XCGstring+","+YCGstring); } } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonReadClick(TObject *Sender) {/* if(IdTCPClient1->Connected()) { LabeledEditLectura->Text=(IdTCPClient1->ReadLn("F",1000)); if (LabeledEditLectura->Text=="") Ingeniería en Automática y Electrónica Industrial A1-5 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder LabeledEditLectura->Text="Lectura vacia"; else LabeledEditEncoder->Text=(IdTCPClient1->ReadLn("F",1000)); } */} //--------------------------------------------------------------------------void __fastcall TForm1::TimerInfoTimer(TObject *Sender) { long Tiempo; // long deliberadamente para casting a ms Tiempo=1000*(App1->Timer->Read()); StatusBarInfo->Panels->Items[0]->Text=" Reloj "+AnsiString(Tiempo); /*switch (Global::GetEstado()) { case Alarma: { StatusBarInfo->Panels->Items[1]->Text="ESTADO break; } case MarchaContinuoEsperando:{ StatusBarInfo->Panels->Items[1]->Text="ESTADO Continuo,Esperando"; break; } case MarchaContinuoEnProceso: { StatusBarInfo->Panels->Items[1]->Text="ESTADO Proceso"; cnt[9]++; break; } case Preparado: { StatusBarInfo->Panels->Items[1]->Text="ESTADO break; } case Marcha1CicloEnProceso: { StatusBarInfo->Panels->Items[1]->Text="ESTADO Proceso"; break; } } */ AUTO: Alarma"; AUTO: AUTO: Continuo,En AUTO: Preparado"; AUTO: 1 Ciclo,En } //--------------------------------------------------------------------------void __fastcall TForm1::LabeledEditOnChange(TObject *Sender) { /* Situacion de cuelgue while (LabeledEditOn->Text==1) { //Form1->ButtonTodo->Click(); } */ } //--------------------------------------------------------------------------void __fastcall TForm1::Digitizer1CameraPresent(TObject *Sender) { Ingeniería en Automática y Electrónica Industrial A1-6 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder ShowMessage("Camara presente"); } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonEtiquetadoClick(TObject *Sender) { ActionEtiquetado->Execute(); } //--------------------------------------------------------------------------- void __fastcall TForm1::CargarClick(TObject *Sender) { ImageMil1->Load(NULL,0); // ImageMil1->Load(NULL,0); Ajusta imagen al tamaño del display } //--------------------------------------------------------------------------void __fastcall TForm1::SalvarClick(TObject *Sender) { ImageMil1->Save(NULL); } //--------------------------------------------------------------------------- void __fastcall TForm1::HistogramapasoapasoClick(TObject *Sender) { if (Histogramapasoapaso->Checked==FALSE) Histogramapasoapaso->Checked=TRUE; else Histogramapasoapaso->Checked=FALSE; } //--------------------------------------------------------------------------void __fastcall TForm1::OtsupasoapasoClick(TObject *Sender) { if (Otsupasoapaso->Checked==FALSE) Otsupasoapaso->Checked=TRUE; else Otsupasoapaso->Checked=FALSE; } //--------------------------------------------------------------------------void __fastcall TForm1::ImagenizdadchaClick(TObject *Sender) { VARIANT vimagen; SAFEARRAY* psaimagen=NULL; SAFEARRAYBOUND rgsabound[2]; const unsigned int cDims=2; int SizeX,SizeY; /* Extracción de imagen desde ImageMil1 */ VariantInit(&vimagen); vimagen.vt=VT_ARRAY|VT_UI1; // tipo de dato: SAFEARRAY de UINT8 Ingeniería en Automática y Electrónica Industrial A1-7 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder SizeX=ImageMil1->SizeX; SizeY=ImageMil1->SizeY; rgsabound[0].cElements=SizeX; rgsabound[0].lLbound=0; rgsabound[1].cElements=SizeY; rgsabound[1].lLbound=0; psaimagen=SafeArrayCreate(VT_UI1,cDims,rgsabound); vimagen.parray=psaimagen; ImageMil1->Get(&vimagen,imSingleBand,imAllBands,0,0,SizeX,SizeY); /*Ya tenemos la imagen...................... */ ImageMil2->Put(vimagen,imSingleBand,imAllBands,0,0,SizeX,SizeY); } //--------------------------------------------------------------------------void __fastcall TForm1::InvierteimagendchaClick(TObject *Sender) { VARIANT vimagen,vimagenINV; SAFEARRAY *psaimagen=NULL,*psaimagenINV=NULL; SAFEARRAYBOUND rgsabound[2]; const unsigned int cDims=2; long rgIndices[2]; int SizeX,SizeY,PixMax; unsigned char pixelIN,pixelOUT; /* Extracción de imagen desde ImageMil2 */ VariantInit(&vimagen); vimagen.vt=VT_ARRAY|VT_UI1; // tipo de dato: SAFEARRAY de UINT8 VariantInit(&vimagenINV); vimagenINV.vt=VT_ARRAY|VT_UI1; // tipo de dato: SAFEARRAY de UINT8 SizeX=ImageMil2->SizeX; SizeY=ImageMil2->SizeY; rgsabound[0].cElements=SizeX; rgsabound[0].lLbound=0; rgsabound[1].cElements=SizeY; rgsabound[1].lLbound=0; psaimagen=SafeArrayCreate(VT_UI1,cDims,rgsabound); psaimagenINV=SafeArrayCreate(VT_UI1,cDims,rgsabound); vimagen.parray=psaimagen; vimagenINV.parray=psaimagenINV; ImageMil2->Get(&vimagen,imSingleBand,imAllBands,0,0,SizeX,SizeY); /*Ya tenemos la imagen...................... */ PixMax=(ImageMil1->MaximumPixelValue); for(int i=0;i<SizeX;i++) { for(int j=0;j<SizeY;j++) { Ingeniería en Automática y Electrónica Industrial A1-8 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder rgIndices[0]=i; rgIndices[1]=j; SafeArrayGetElement(psaimagen,rgIndices,&pixelIN); pixelOUT=PixMax-pixelIN; SafeArrayPutElement(psaimagenINV,rgIndices,&pixelOUT); } } ImageMil2->Put(vimagenINV,imSingleBand,imAllBands,0,0,SizeX,SizeY); VariantClear(&vimagen); VariantClear(&vimagenINV); } //--------------------------------------------------------------------------void __fastcall TForm1::ImagenpruebasimpleClick(TObject *Sender) { VARIANT vimagen; SAFEARRAY *psaimagen=NULL; SAFEARRAYBOUND rgsabound[2]; const unsigned int cDims=2; long rgIndices[2]; int SizeX,SizeY; int ValorBajo,ValorAlto; unsigned char pixelOUT; ValorBajo=0; ValorAlto=255; VariantInit(&vimagen); vimagen.vt=VT_ARRAY|VT_UI1; SizeX=ImageMil2->SizeX; SizeY=ImageMil2->SizeY; rgsabound[0].cElements=SizeX; rgsabound[0].lLbound=0; rgsabound[1].cElements=SizeY; rgsabound[1].lLbound=0; // tipo de dato: SAFEARRAY de UINT8 psaimagen=SafeArrayCreate(VT_UI1,cDims,rgsabound); vimagen.parray=psaimagen; for(int i=0;i<SizeX;i++) { for(int j=0;j<SizeY;j++) { rgIndices[0]=i; rgIndices[1]=j; pixelOUT=ValorBajo; if ((i>50)&(i<100)&(j>200)&(j<300)) pixelOUT=ValorAlto; SafeArrayPutElement(psaimagen,rgIndices,&pixelOUT); } } ImageMil2->Put(vimagen,imSingleBand,imAllBands,0,0,SizeX,SizeY); VariantClear(&vimagen); } //--------------------------------------------------------------------------- Ingeniería en Automática y Electrónica Industrial A1-9 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder void __fastcall TForm1::EnviaceroaRobotClick(TObject *Sender) { if(IdTCPClient1->Connected()) IdTCPClient1->WriteLn("Cero,0,0,0,0,0"); else ShowMessage ("¡¡¡No hay conexión con el Robot!!!"); } //--------------------------------------------------------------------------void __fastcall TForm1::ConectarClick(TObject *Sender) { if(! IdTCPClient1->Connected()) { IdTCPClient1->Connect(); } } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonStartClick(TObject *Sender) { if (Global::GetEstado()==Preparado) Global::NuevoEstado(MarchaContinuoEsperando); SpeedButtonManual->Enabled=FALSE; ButtonStart->Enabled=FALSE; ButtonStop->Enabled=TRUE; } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonStopClick(TObject *Sender) { Global::NuevoEstado(Preparado); StatusBarInfo->Panels->Items[1]->Text= "ESTADO AUTO: Preparado"; SpeedButtonManual->Enabled=TRUE; ButtonStart->Enabled=TRUE; ActionCompleto->Tag=0; // Marca de proceso ocupado } //--------------------------------------------------------------------------void __fastcall TForm1::ActionHistogramaExecute(TObject *Sender) { VARIANT vimagen; SAFEARRAY* psaimagen=NULL; SAFEARRAYBOUND rgsabound[2]; const unsigned int cDims=2; long rgIndices[2]; int SizeX,SizeY; unsigned char pixel,*puntpixel; double histograma[NivelesGris],vectoromega[NivelesGris]; double vectorsigmabsquared[NivelesGris]; double mu_T,mu,omega,sigma_b_squared,sigma_b_squared_MAX; int umbral_otsu; long Tini,Tfinhist,Tfinotsu; // long deliberadamente para casting a ms Ingeniería en Automática y Electrónica Industrial A1-10 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder Tini=1000*(App1->Timer->Read()); /* Extracción de imagen desde ImageMil1 */ VariantInit(&vimagen); vimagen.vt=VT_ARRAY|VT_UI1; // tipo de dato: SAFEARRAY de UINT8 SizeX=ImageMil1->SizeX; SizeY=ImageMil1->SizeY; rgsabound[0].cElements=SizeX; rgsabound[0].lLbound=0; rgsabound[1].cElements=SizeY; rgsabound[1].lLbound=0; psaimagen=SafeArrayCreate(VT_UI1,cDims,rgsabound); vimagen.parray=psaimagen; ImageMil1->Get(&vimagen,imSingleBand,imAllBands,0,0,SizeX,SizeY); //puntpixel= (unsigned char *) psaimagen->pvData; /*Ya tenemos la imagen...................... */ /* Obtención del histograma */ //ShowMessage("Voy a obtener histograma"); for(int h=0;h<NivelesGris;h++) histograma[h]=0; // Reset histograma for(int i=0;i<SizeX;i++) { for(int j=0;j<SizeY;j++) { rgIndices[0]=i; rgIndices[1]=j; SafeArrayGetElement(psaimagen,rgIndices,&pixel ); histograma[pixel]+=1; //histograma[*puntpixel]+=1; } } VariantClear(&vimagen); Tfinhist=1000*(App1->Timer->Read()); /* Metodo de Otsu. Primero se normaliza el histograma en [0,1] y se obtiene la media total*/ mu_T=0; for(int t=0;t<NivelesGris;t++){ histograma[t]=histograma[t]/(SizeX*SizeY); mu_T+=t*histograma[t]; if (Histogramapasoapaso->Checked==TRUE) ShowMessage( "histograma["+AnsiString(t)+"]="+ AnsiString(histograma[t]*SizeX*SizeY)+ "\nSizeX="+AnsiString(SizeX)+ "\nSizeY="+AnsiString(SizeY)+ "\nSizeX*SizeY="+AnsiString(SizeX*SizeY)+ "\nhistograma["+AnsiString(t)+"]="+ Ingeniería en Automática y Electrónica Industrial A1-11 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder AnsiString(histograma[t]) ); } StaticTextMedia->Caption="Media="+AnsiString((int)mu_T); sigma_b_squared_MAX=0; mu=0; omega=0; if (mu_T>0) { for(int t=0;t<NivelesGris;t++){ /* Probabilidad de la clase t>umbral */ omega+=histograma[t]; /* media de la clase t<umbral */ mu+=t*histograma[t]; /* Zona útil del histograma 0.001-0.999 */ if ((omega>0.001)&&(omega<0.999)) /* VARIANZA ENTRE CLASES */ sigma_b_squared=((mu_T*omega-mu)*(mu_T*omega-mu))/ (omega*(1-omega)); else sigma_b_squared=0; /* vectores para mostrar en gráfico */ vectoromega[t]=omega; vectorsigmabsquared[t]=sigma_b_squared; if (sigma_b_squared>=sigma_b_squared_MAX) { sigma_b_squared_MAX=sigma_b_squared; umbral_otsu=t; } if (Otsupasoapaso->Checked==TRUE) ShowMessage("t="+AnsiString(t)+"\n"+ "omega="+AnsiString(omega)+"\n"+ "mu="+AnsiString(mu)+"\n"+ "(mu_T*omega-mu)="+AnsiString(mu_T*omega-mu)+"\n"+ "cuadrado="+AnsiString((mu_T*omega-mu)*(mu_T*omega-mu)) +"\n"+ "(omega*(1-omega))="+AnsiString(omega*(1-omega))+"\n"+ "sigma_b_squared="+AnsiString(sigma_b_squared)); /* Test Chart */ histogramatest[t]=histograma[t]; vectoromegatest[t]=vectoromega[t]; vectorsigmabsquaredtest[t]=vectorsigmabsquared[t]; PixSizetest=NivelesGris; } else } StaticTextMedia->Caption="Todo negro!"; StaticTextVarMax>Caption="VarMax="+AnsiString((int)sigma_b_squared_MAX); /* Muestra el umbral calculado, y lo "convierte" en variable global */ if (umbral_otsu<UmbralOtsuMinimo) umbral_otsu=UmbralOtsuMinimo; ScrollBarUmbral->Position=umbral_otsu; StaticTextUmbral->Caption=AnsiString(umbral_otsu); if (CheckBoxGrafica->Checked==TRUE) { /* Representación gráfica de histograma y vectores estadísticos */ ChartHistograma->Series[0]->Clear(); Ingeniería en Automática y Electrónica Industrial A1-12 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder ChartHistograma->Series[0]->AddArray( histograma, NivelesGris); ChartHistograma->Series[1]->Clear(); ChartHistograma->Series[1]->AddArray( vectoromega, NivelesGris); ChartHistograma->Series[2]->Clear(); ChartHistograma->Series[2]->AddArray( vectorsigmabsquared, NivelesGris); } Tfinotsu=1000*(App1->Timer->Read()); StaticTextTHist->Caption="His "+AnsiString(Tfinhist-Tini)+"ms"; StaticTextTOtsu->Caption="Ots "+AnsiString(Tfinotsu-Tfinhist)+"ms"; } //--------------------------------------------------------------------------void __fastcall TForm1::ActionCapturaExecute(TObject *Sender) { long Tini,Tfin; // long deliberadamente para casting a ms Tini=1000*(App1->Timer->Read()); if (Digitizer1->GrabInProgress==TRUE) Digitizer1->Halt(); Digitizer1->Grab(); // Graba sobre ImageMil1 Tfin=1000*(App1->Timer->Read()); StaticTextTGrab->Caption="Fot "+AnsiString(Tfin-Tini)+"ms"; } //--------------------------------------------------------------------------void __fastcall TForm1::ActionBinarizaExecute(TObject *Sender) { VARIANT vimagen,vimagenBIN; SAFEARRAY *psaimagen=NULL,*psaimagenBIN=NULL; SAFEARRAYBOUND rgsabound[2]; const unsigned int cDims=2; long rgIndices[2]; int SizeX,SizeY; int umbral; unsigned char pixelIN,pixelOUT; long Tini,Tfin; // long deliberadamente para casting a ms Tini=1000*(App1->Timer->Read()); umbral=ScrollBarUmbral->Position; /* Extracción de imagen desde ImageMil1 */ VariantInit(&vimagen); vimagen.vt=VT_ARRAY|VT_UI1; // tipo de dato: SAFEARRAY de UINT8 VariantInit(&vimagenBIN); vimagenBIN.vt=VT_ARRAY|VT_UI1; // tipo de dato: SAFEARRAY de UINT8 SizeX=ImageMil1->SizeX; SizeY=ImageMil1->SizeY; rgsabound[0].cElements=SizeX; rgsabound[0].lLbound=0; rgsabound[1].cElements=SizeY; rgsabound[1].lLbound=0; Ingeniería en Automática y Electrónica Industrial A1-13 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder psaimagen=SafeArrayCreate(VT_UI1,cDims,rgsabound); psaimagenBIN=SafeArrayCreate(VT_UI1,cDims,rgsabound); vimagen.parray=psaimagen; vimagenBIN.parray=psaimagenBIN; ImageMil1->Get(&vimagen,imSingleBand,imAllBands,0,0,SizeX,SizeY); /*Ya tenemos la imagen en psaimagen */ for(int i=0;i<SizeX;i++) { for(int j=0;j<SizeY;j++) { rgIndices[0]=i; rgIndices[1]=j; SafeArrayGetElement(psaimagen,rgIndices,&pixelIN); if (pixelIN<=umbral) pixelOUT=ValorBinarioBajo; else pixelOUT=ValorBinarioAlto; SafeArrayPutElement(psaimagenBIN,rgIndices,&pixelOUT); } } /* Ya tenemos la imagen binarizada en psaimagenBIN */ ImageMil2->Put(vimagenBIN,imSingleBand,imAllBands,0,0,SizeX,SizeY); VariantClear(&vimagen); VariantClear(&vimagenBIN); Tfin=1000*(App1->Timer->Read()); StaticTextTBin->Caption="Bin "+AnsiString(Tfin-Tini)+"ms"; } //--------------------------------------------------------------------------void __fastcall TForm1::ActionBusquedaExecute(TObject *Sender) { VARIANT vimagen; SAFEARRAY* psaimagen=NULL; SAFEARRAYBOUND rgsabound[2]; const unsigned int cDims=2; long rgIndices[2]; int SizeX,SizeY; unsigned char pixel; long x,y,den; int CGpix[2],CGmm[2],Npix,Npiezas; long Tini,Tfin; // long deliberadamente para casting a ms Tini=1000*(App1->Timer->Read()); /* Extracción de imagen desde ImageMil2 */ VariantInit(&vimagen); vimagen.vt=VT_ARRAY|VT_UI1; // tipo de dato: SAFEARRAY de UINT8 SizeX=ImageMil1->SizeX; Ingeniería en Automática y Electrónica Industrial A1-14 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder SizeY=ImageMil1->SizeY; rgsabound[0].cElements=SizeX; rgsabound[0].lLbound=0; rgsabound[1].cElements=SizeY; rgsabound[1].lLbound=0; psaimagen=SafeArrayCreate(VT_UI1,cDims,rgsabound); vimagen.parray=psaimagen; ImageMil2->Get(&vimagen,imSingleBand,imAllBands,0,0,SizeX,SizeY); /*Ya tenemos la imagen...................... */ x=y=den=0; for(int i=0;i<SizeX;i++) { for(int j=0;j<SizeY;j++) { rgIndices[0]=i; rgIndices[1]=j; SafeArrayGetElement(psaimagen,rgIndices,&pixel); /* Para cada pixel...*/ x=x+i*(pixel==ValorBinarioAlto); y=y+j*(pixel==ValorBinarioAlto); den=den+(pixel==ValorBinarioAlto); } } VariantClear(&vimagen); if (den==0) { CGpix[0]=(SizeX/2); CGpix[1]=(SizeY/2); } else { CGpix[0]=(int)(x/den); CGpix[1]=(int)(y/den); } Npix=den; GraphicContext1->DrawingRegion->CenterX=CGpix[0]; GraphicContext1->DrawingRegion->CenterY=CGpix[1]; GraphicContext1->Cross(45); CGmm[0]=PixToMm*CGpix[0]; CGmm[1]=PixToMm*CGpix[1]; /* Comprobacion del tipo de pieza detectada */ if ((Npix>6500)&&(Npix<7500)) { Npiezas=1; //StaticTextTipoImagen->Caption="CIRC.PEQUEÑO"; } else { if ((Npix>11500)&&(Npix<13000)) { Npiezas=1; //StaticTextTipoImagen->Caption="CIRC.GRANDE"; } else { Ingeniería en Automática y Electrónica Industrial A1-15 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder } Npiezas=0; //StaticTextTipoImagen->Caption="COSAS RARAS"; } Global::SetNpiezas(Npiezas); Global::SetXCG(0,CGmm[0]); Global::SetYCG(0,CGmm[1]); //StaticTextCG>Caption="CG="+AnsiString(CGmm[0])+","+AnsiString(CGmm[1]); //StaticTextNpix->Caption="Nºpix="+AnsiString(Npix); Tfin=1000*(App1->Timer->Read()); StaticTextTCG->Caption="Sim "+AnsiString(Tfin-Tini)+"ms"; } //--------------------------------------------------------------------------void __fastcall TForm1::TimerRunTimer(TObject *Sender) { if (Global::GetEstado()==MarchaContinuoEsperando) { cnt[6]++; Global::NuevoEstado(MarchaContinuoEnProceso); StatusBarInfo->Panels->Items[1]->Text= "ESTADO AUTO: Continuo,En Proceso"; //ActionCompleto->Execute(); ActionCompletoMultiple->Execute(); if (Global::GetEstado()==MarchaContinuoEnProceso) { cnt[7]++; Global::NuevoEstado(MarchaContinuoEsperando); StatusBarInfo->Panels->Items[1]->Text= "ESTADO AUTO: Continuo,Esperando"; } } else { if (Global::GetEstado()==MarchaContinuoEnProceso) cntsolapamientos++; } cnt[8]++; } //--------------------------------------------------------------------------void __fastcall TForm1::SpeedButtonManualClick(TObject *Sender) { ButtonGrab->Enabled=TRUE; ButtonHistograma->Enabled=TRUE; ButtonBinariza->Enabled=TRUE; ButtonCG->Enabled=TRUE; ButtonGrabCont->Enabled=TRUE; ButtonErosion->Enabled=TRUE; ButtonEtiqueta->Enabled=TRUE; ArchivoImagen->Enabled=TRUE; HerramientasVision->Enabled=TRUE; HerramientasRobot->Enabled=TRUE; Ingeniería en Automática y Electrónica Industrial A1-16 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder ButtonStart->Enabled=FALSE; ButtonStop->Enabled=FALSE; ButtonStart1Ciclo->Enabled=FALSE; } //--------------------------------------------------------------------------void __fastcall TForm1::SpeedButtonAutoClick(TObject *Sender) { ButtonGrab->Enabled=FALSE; ButtonHistograma->Enabled=FALSE; ButtonBinariza->Enabled=FALSE; ButtonCG->Enabled=FALSE; ButtonGrabCont->Enabled=FALSE; ButtonErosion->Enabled=FALSE; ButtonEtiqueta->Enabled=FALSE; ArchivoImagen->Enabled=FALSE; HerramientasVision->Enabled=FALSE; HerramientasRobot->Enabled=FALSE; ButtonStart->Enabled=TRUE; ButtonStop->Enabled=TRUE; ButtonStart1Ciclo->Enabled=TRUE; } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonStart1CicloClick(TObject *Sender) { if (Global::GetEstado()==Preparado) { Global::NuevoEstado(Marcha1CicloEnProceso); StatusBarInfo->Panels->Items[1]->Text= "ESTADO AUTO: 1 Ciclo,En Proceso"; //ActionCompleto->Execute(); ActionCompletoMultiple->Execute(); Global::NuevoEstado(Preparado); StatusBarInfo->Panels->Items[1]->Text= "ESTADO AUTO: Preparado"; } else if (Global::GetEstado()==Marcha1CicloEnProceso) cntsolapamientos1ciclo++; } //--------------------------------------------------------------------------void __fastcall TForm1::ActionCompletoExecute(TObject *Sender) { AnsiString RespuestaRobot,TramaEnviada,ResultadoCompleto; int Nciclos; bool ComOk; int ContadorTramasBasura; long Tini,Tfin,Tcom; // long deliberadamente para casting a ms /* Contador de ciclos de ActionCompleto */ Global::IncNciclos(); Nciclos=Global::GetNciclos(); /* Conexión automática con Robot */ Ingeniería en Automática y Electrónica Industrial A1-17 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder if((!IdTCPClient1->Connected()) && (CheckBoxComunicate->Checked==TRUE)) IdTCPClient1->Connect(); Tini=1000*(App1->Timer->Read()); if (IdTCPClient1->Connected()) { if(CheckBoxComunicate->Checked==TRUE) ComOk=TRUE; else { ComOk=FALSE; ResultadoCompleto="No seleccionado Comunicate"; } } else { ComOk=FALSE; ResultadoCompleto="No conectado"; } /* Limpieza del buffer. En caso de haber enviado cadenas PCTrigger al Robot mientras este se encuentra en PAUSE, porque se ha pulsado STOP o bien por alguna alarma, al reiniciarse procesará y responderá a todos los PCTrigger llenando el buffer de recepción del PC de basura que el PC iría recogiendo dessincronizadamente con ReadLn. Por eso se debe vaciar al comienzo de cada secuencia */ if (ComOk){ while (IdTCPClient1->ReadLn("\r",5)!="") ContadorTramasBasura++; } /* Enviar trigger software al Robot, cadena de texto "PCTrigger" */ if (ComOk) { TramaEnviada="PCTrigger,"+AnsiString(Nciclos)+",0,0,0"; IdTCPClient1->WriteLn(TramaEnviada); StatusBarInfo->Panels->Items[3]->Text="Enviado: "+TramaEnviada; ResultadoCompleto="Enviado PCTrigger"; } /* Captura de imagen, la cámara está en modo video (default). El tiempo empleado será un error de encoder para el tracking! */ ActionCaptura->Execute(); /* Confirmación de respuesta del robot, cadena "ACKPCTrigger"+Nciclos */ if (ComOk) { RespuestaRobot=IdTCPClient1->ReadLn("\r",TimeoutTCP); StatusBarInfo->Panels->Items[4]->Text="Recibido: "+RespuestaRobot; if (RespuestaRobot!=("ACKPCTrigger"+AnsiString(Nciclos))) { ComOk=FALSE; ResultadoCompleto="Timeout ACKCPTrigger"; } else ResultadoCompleto="Recibido ACKPCTrigger"; } /* Procesamiento de la imagen */ if (CheckBoxUmbralOtsu->Checked==TRUE) ActionHistograma->Execute(); ActionBinariza->Execute(); Ingeniería en Automática y Electrónica Industrial // Metodo Otsu seleccionado A1-18 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder ActionBusqueda->Execute(); /* Confirmación de que hay datos que merezca la pena enviar */ if (ComOk) { if (Global::GetNpiezas()==0) { ComOk=False; ResultadoCompleto="Npiezas=0, no hay datos listos"; } } Tcom=1000*(App1->Timer->Read()); /* Envio de datos de posicion */ if (ComOk) { TramaEnviada= "Datos,"+ AnsiString(Nciclos)+","+ AnsiString(Global::GetXCG(0))+","+ AnsiString(Global::GetYCG(0))+","+ "1,0,0"; IdTCPClient1->WriteLn(TramaEnviada); StatusBarInfo->Panels->Items[3]->Text="Enviado: "+TramaEnviada; ResultadoCompleto="Enviados los datos"; } /* Confirmación de respuesta del robot, cadena "ACKDatos" */ if (ComOk) { RespuestaRobot=IdTCPClient1->ReadLn("\r",TimeoutTCP); StatusBarInfo->Panels->Items[4]->Text="Recibido: "+RespuestaRobot; if (RespuestaRobot!="ACKDatos") { ComOk=FALSE; ResultadoCompleto="Timeout ACKDatos"; } else ResultadoCompleto="Recibido ACKDatos"; } Tfin=1000*(App1->Timer->Read()); StaticTextTCompleto->Caption="TOT "+AnsiString(Tfin-Tini)+"ms"; StaticTextTCom->Caption="Com "+AnsiString(Tfin-Tcom)+"ms"; MemoComunicaciones->Lines->Append(AnsiString(Global::GetNciclos())+": "+ ResultadoCompleto); } //--------------------------------------------------------------------------void __fastcall TForm1::EnviaXYalRobot1Click(TObject *Sender) { /* Envio de datos de posicion */ if ((IdTCPClient1->Connected())) IdTCPClient1->WriteLn( AnsiString(Global::GetXCG(0))+","+ AnsiString(Global::GetYCG(0))+","+ "1"); else ShowMessage ("¡¡¡No hay conexión con el Robot!!!"); } Ingeniería en Automática y Electrónica Industrial A1-19 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder //--------------------------------------------------------------------------void __fastcall TForm1::DesconectarClick(TObject *Sender) { IdTCPClient1->Disconnect(); } //--------------------------------------------------------------------------void __fastcall TForm1::ActionErosionExecute(TObject *Sender) { VARIANT vimagenIN,vimagenOUT; SAFEARRAY *psaimagenIN=NULL,*psaimagenOUT=NULL; SAFEARRAYBOUND rgsabound[2]; const unsigned int cDims=2; long rgIndices[2],rgIndicesEntorno[2]; int SizeX,SizeY; int umbral; unsigned char pixelIN,pixelOUT; long Tini,Tfin; // long deliberadamente para casting a ms Tini=1000*(App1->Timer->Read()); /* Extracción de imagen desde ImageMil1 */ VariantInit(&vimagenIN); vimagenIN.vt=VT_ARRAY|VT_UI1; // tipo de dato: SAFEARRAY de UINT8 VariantInit(&vimagenOUT); vimagenOUT.vt=VT_ARRAY|VT_UI1; // tipo de dato: SAFEARRAY de UINT8 SizeX=ImageMil1->SizeX; SizeY=ImageMil1->SizeY; rgsabound[0].cElements=SizeX; rgsabound[0].lLbound=0; rgsabound[1].cElements=SizeY; rgsabound[1].lLbound=0; psaimagenIN=SafeArrayCreate(VT_UI1,cDims,rgsabound); psaimagenOUT=SafeArrayCreate(VT_UI1,cDims,rgsabound); vimagenIN.parray=psaimagenIN; vimagenOUT.parray=psaimagenOUT; ImageMil2->Get(&vimagenIN,imSingleBand,imAllBands,0,0,SizeX,SizeY); /*Ya tenemos la imagen en psaimagenIN, seguimos.. */ /* Asignación dinámica de memoria para matrices mascara y entorno */ int **mascara, **entorno; mascara=new int* [OrdenDeMascara]; for (int nfila=0;nfila<OrdenDeMascara;nfila++) mascara[nfila]=new int [OrdenDeMascara]; /* entorno=new int* [OrdenDeMascara]; for (int nfila=0;nfila<OrdenDeMascara;nfila++) entorno[nfila]=new int [OrdenDeMascara]; */ Ingeniería en Automática y Electrónica Industrial A1-20 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder /* Valores iniciales de matrices mascara y entorno. La matriz mascara será de 1s, para erosion maxima. La matriz entorno será de 0s, para inicio fuera de imagen. */ for (int fil=0;fil<OrdenDeMascara;fil++) { for (int col=0;col<OrdenDeMascara;col++) { mascara[fil][col]=1; //entorno[fil][col]=0; } } /* Barrido de imagen */ int resultadomascara,ipix,jpix; int radiomascara,limiteerosion; /* Radio de la matriz mascara: */ radiomascara=OrdenDeMascara/2; //ShowMessage("radiomascara="+AnsiString(radiomascara)); /* Valor límite para decidir la erosión del pixel */ limiteerosion=OrdenDeMascara*OrdenDeMascara*ValorBinarioAlto; for(int i=0;i<SizeX;i++) { for(int j=0;j<SizeY;j++) { rgIndices[0]=i; rgIndices[1]=j; SafeArrayGetElement(psaimagenIN,rgIndices,&pixelIN); if (pixelIN==ValorBinarioAlto) { /* Barrido de cada entorno de pixel blanco */ resultadomascara=0; for (int fil=0;fil<OrdenDeMascara;fil++) { /**** bloque desplazada a la izda ****/ for (int col=0;col<OrdenDeMascara;col++) { /* Para cada pixel del entorno */ ipix=i+fil-radiomascara; jpix=j+col-radiomascara; if ((ipix>0)&&(ipix<SizeX)&&(jpix>0)&&(jpix<SizeY)) { /* Acceso al pixel, del entorno */ cnt[9]++; rgIndicesEntorno[0]=ipix; rgIndicesEntorno[1]=jpix; SafeArrayGetElement(psaimagenIN,rgIndicesEntorno,&pixelIN); //entorno[fil][col]=pixelIN //resultadomascara+=mascara[fil][col]*pixelIN; resultadomascara+=pixelIN; if (resultadomascara>=limiteerosion ) { pixelOUT=ValorBinarioAlto; SafeArrayPutElement(psaimagenOUT,rgIndices,&pixelOUT); } } } /**** Fin bloque desplazada a la izda ****/ } } } } Ingeniería en Automática y Electrónica Industrial A1-21 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder /* Ya tenemos la imagen erosionada en psaimagenOUT */ ImageMil2->Put(vimagenOUT,imSingleBand,imAllBands,0,0,SizeX,SizeY); /* Liberando memoria, que después pasa lo que pasa */ for (int nfila=0;nfila<OrdenDeMascara;nfila++) delete [] mascara[nfila]; delete [] mascara; /* for (int nfila=0;nfila<OrdenDeMascara;nfila++) delete [] entorno[nfila]; delete [] entorno; */ VariantClear(&vimagenIN); VariantClear(&vimagenOUT); Tfin=1000*(App1->Timer->Read()); StaticTextErosion->Caption="Ero "+AnsiString(Tfin-Tini)+"ms"; } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonErosionClick(TObject *Sender) { ActionErosion->Execute(); } //--------------------------------------------------------------------------void __fastcall TForm1::ActionEtiquetadoExecute(TObject *Sender) { VARIANT vimagen; SAFEARRAY* psaimagen=NULL; SAFEARRAYBOUND rgsabound[2]; const unsigned int cDims=2; long rgIndices[2]; int SizeX,SizeY; unsigned char pixel; long x,y,den; long Tini,Tfin; // long deliberadamente para casting a ms /* En los vectores enlaces y clases la componente inicial no se usa */ int enlaces[MaximoEtiquetas+1],clases[MaximoEtiquetas+1]; int EtiquetaMaxima,ClaseMaxima; Tini=1000*(App1->Timer->Read()); /* Extracción de imagen desde ImageMil2 */ VariantInit(&vimagen); vimagen.vt=VT_ARRAY|VT_UI1; // tipo de dato: SAFEARRAY de UINT8 SizeX=ImageMil1->SizeX; SizeY=ImageMil1->SizeY; rgsabound[0].cElements=SizeX; Ingeniería en Automática y Electrónica Industrial A1-22 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder rgsabound[0].lLbound=0; rgsabound[1].cElements=SizeY; rgsabound[1].lLbound=0; psaimagen=SafeArrayCreate(VT_UI1,cDims,rgsabound); vimagen.parray=psaimagen; ImageMil2->Get(&vimagen,imSingleBand,imAllBands,0,0,SizeX,SizeY); /*Ya tenemos la imagen...................... */ cnt[0]=cnt[1]=cnt[2]=cnt[3]=cnt[4]=cnt[5]=0; /* Asignación dinámica de memoria para matriz etiqueta */ //ShowMessage(AnsiString(SizeX)+","+AnsiString(SizeY)); /*int **etiquetas; etiquetas=new int* [SizeX]; for (int nfila=0;nfila<SizeX;nfila++) etiquetas[nfila]=new int [SizeY]; */ /* Reset inicial de vector enlaces, de dimensión MaximoEtiquetas+1 */ for (int i=0;i<=MaximoEtiquetas;i++) enlaces[i]=0; /* Recorrido de etiquetado, las filas y columnas extremas se etiquetan a 0. Si se acaban las etiquetas disponibles, el resto de imagen se etiqueta a 0. Por eso la componente 0 de los vectores enlaces y clases no se utilizará */ int NuevaEtiqueta=1,arriba,izda; for(int i=0;i<SizeX;i++) { for(int j=0;j<SizeY;j++) { rgIndices[0]=i; rgIndices[1]=j; SafeArrayGetElement(psaimagen,rgIndices,&pixel); if ((pixel==ValorBinarioAlto) &&(i>0)&&(i<SizeX-1)&&(j>0)&&(j<SizeY-1) && (NuevaEtiqueta<MaximoEtiquetas)) { arriba=etiquetas[i][j-1]; izda=etiquetas[i-1][j]; /* Los casos siguientes están ordenados de mayor a menor número de ocurrencias, para optimizar algoritmo*/ if (arriba!=0) { if (izda!=0) { if (arriba==izda){ /* 4-conectado arriba e izda */ //cnt[0]++; etiquetas[i][j]=arriba; } else { if (arriba>izda) { /* 4-conectado arriba e izda con diferentes etiquetas */ //cnt[2]++; etiquetas[i][j]=izda; enlaces[arriba]=izda; } Ingeniería en Automática y Electrónica Industrial A1-23 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder else { if (arriba<izda) { /* 4-conectado arriba e izda con diferentes etiquetas */ //cnt[1]++; etiquetas[i][j]=arriba; enlaces[izda]=arriba; } } } } else { /* conectado arriba */ //cnt[3]++; etiquetas[i][j]=arriba; } } else { // arriba==0 if (izda!=0){ /* conectado izda */ //cnt[4]++; etiquetas[i][j]=izda; } else { /* No conectado ni arriba ni izda, nueva etiqueta */ //cnt[5]++; etiquetas[i][j]=NuevaEtiqueta; enlaces[NuevaEtiqueta]=-1; NuevaEtiqueta++; } } //marca } else etiquetas[i][j]=0; } } EtiquetaMaxima=NuevaEtiqueta-1; EtiquetaMaximatest=EtiquetaMaxima; /* Agrupación de etiquetas en clases, según las conexiones recogidad en enlaces[]. Si se agotan las clases disponibles, se mantiene la última clase */ int NuevaClase=1; int padre,abuelo; for (int c=0;c<=EtiquetaMaxima;c++) { enlacestest[c]=enlaces[c]; padre=enlaces[c]; /* Si padre=0 esa etiqueta no se usa. Si padre=-1 esa etiqueta es la primera del objeto, no hay abuelo */ if (padre>0) abuelo=enlaces[padre]; else abuelo=0; /* Si hay abuelo el enlace lo hereda, si no queda como está. El proceso es contiuo y no se requiere recursividad, puesto que enlaces se va compactando y el parentesco mayor posible es abuelo*/ if (abuelo>0) enlaces[c]=abuelo; Ingeniería en Automática y Electrónica Industrial A1-24 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder else enlaces[c]=padre; /* Renumeración de etiquetas en clases, enlace[]= -1 inicia secuencia */ if (enlaces[c]==-1) { clases[c]=NuevaClase; if (NuevaClase<MaximoClases) NuevaClase++; } else clases[c]=clases[enlaces[c]]; } clasestest[c]=clases[c]; /* la última clase se desprecia incluso en caso de ser igual a MaximoClases, puesto que entonces esa clase agruparía todo el exceso de imagen */ ClaseMaxima=NuevaClase-1; ClaseMaximatest=ClaseMaxima; /************** Análisis de objetos *************************************/ /* Declaración e inicialización de variables que intervienen. Estos vectores se utilizan desde la componente 0, no desde 1 como ocurre con enlaces[] y clases[] */ long xvector[MaximoClases],yvector[MaximoClases]; int Npixvector[MaximoClases],NpixPeriferia[MaximoClases]; int XCG[MaximoClases],YCG[MaximoClases]; AnsiString TipoPieza[MaximoClases]; int Npiezas; for (int c=0;c<MaximoClases;c++) { xvector[c]=0; yvector[c]=0; Npixvector[c]=0; NpixPeriferia[c]=0; } /* Barrido de la imagen etiquetas[][] */ int ClasePixel; for(int i=0;i<SizeX;i++) { for(int j=0;j<SizeY;j++) { if (etiquetas[i][j]>0) { ClasePixel=clases[etiquetas[i][j]]; xvector[ClasePixel-1]+=i; yvector[ClasePixel-1]+=j; Npixvector[ClasePixel-1]+=1; if ((i<AnchoPeriferia)||(i>SizeX-AnchoPeriferia)|| (j<AnchoPeriferia)||(j>SizeY-AnchoPeriferia) ) NpixPeriferia[ClasePixel-1]+=1; } } } /* Obtención de coordenadas de posición y selección de piezas válidas */ int Npix; bool PiezaValida; Npiezas=0; for (int c=0;c<ClaseMaxima;c++) { if (Npixvector[c]>0) { // Condición de seguridad redundante xvector[c]=xvector[c]/Npixvector[c]; yvector[c]=yvector[c]/Npixvector[c]; Ingeniería en Automática y Electrónica Industrial A1-25 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder Npix=Npixvector[c]; if (NpixPeriferia[c]>MaxPixPeriferia) { PiezaValida=FALSE; TipoPieza[c]="PERIFERICO"; } else { if ((Npix>MinPequeno)&&(Npix<MaxPequeno)) { PiezaValida=TRUE; TipoPieza[c]="CIRC.PEQUEÑO"; } else { if ((Npix>MinGrande)&&(Npix<MaxGrande)) { PiezaValida=TRUE; TipoPieza[c]="CIRC.GRANDE"; } else { PiezaValida=FALSE; TipoPieza[c]="COSAS RARAS"; } } } if (PiezaValida) { /* Centro de gravedad, convertido de pixel a mm */ XCG[Npiezas]=(int)(PixToMm*xvector[c]); YCG[Npiezas]=(int)(PixToMm*yvector[c]); Npiezas++; } } } /* COLOREA IMAGEN ETIQUETADA. El display se traga valores por encima de 255.*/ if (CheckBoxColorea->Checked==TRUE) { for(int i=0;i<SizeX;i++) { for(int j=0;j<SizeY;j++) { if (etiquetas[i][j]>0) pixel=clases[etiquetas[i][j]]*50; else pixel=0; rgIndices[0]=i; rgIndices[1]=j; SafeArrayPutElement(psaimagen,rgIndices,&pixel); } } ImageMil2->Put(vimagen,imSingleBand,imAllBands,0,0,SizeX,SizeY); } /* Ya no se va a requerir la memoria de la imagen */ VariantClear(&vimagen); /* Liberando memoria, que después pasa lo que pasa */ /*for (int nfila=0;nfila<SizeX;nfila++) delete [] etiquetas[nfila]; delete [] etiquetas; */ Ingeniería en Automática y Electrónica Industrial A1-26 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder /* Información en pantalla */ //MemoEtiquetado->Lines->Clear(); MemoEtiquetado->Lines->Append("-----------------------"); MemoEtiquetado->Lines->Append("Cosas encontradas: "+AnsiString(ClaseMaxima)); for (int c=0;c<ClaseMaxima;c++) { if (Npixvector[c]>0) { // Condición de seguridad redundante GraphicContext1->DrawingRegion->CenterX=xvector[c]; GraphicContext1->DrawingRegion->CenterY=yvector[c]; GraphicContext1->Cross(5); MemoEtiquetado->Lines->Append("Cosa "+AnsiString(c+1)+": "+ AnsiString((int)(PixToMm*xvector[c]))+", "+ AnsiString((int)(PixToMm*yvector[c]))+", "+ AnsiString(Npixvector[c])+","+ TipoPieza[c]); } } /* Escritura de variables globales de resultado */ Global::SetNpiezas(Npiezas); MemoEtiquetado->Lines->Append("Piezas validas: "+AnsiString(Npiezas)); for (int c=0;c<Npiezas;c++) { Global::SetXCG(c,XCG[c]); Global::SetYCG(c,YCG[c]); MemoEtiquetado->Lines->Append("Pieza "+AnsiString(c+1)+": "+ AnsiString(XCG[c])+", "+ AnsiString(YCG[c])); } Tfin=1000*(App1->Timer->Read()); StaticTextEtiquetado->Caption="Mul "+AnsiString(Tfin-Tini)+"ms"; } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonEtiquetaClick(TObject *Sender) { ActionEtiquetado->Execute(); } //--------------------------------------------------------------------------void __fastcall TForm1::ActionCompletoMultipleExecute(TObject *Sender) { AnsiString RespuestaRobot,TramaEnviada,ResultadoCompleto; int Nciclos; bool ComOk; int ContadorTramasBasura; long Tini,Tfin,Tcom; // long deliberadamente para casting a ms Tini=1000*(App1->Timer->Read()); /* Contador de ciclos de ActionCompleto */ Global::IncNciclos(); Nciclos=Global::GetNciclos(); Ingeniería en Automática y Electrónica Industrial A1-27 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder /* Conexión automática con Robot */ if (CheckBoxComunicate->Checked==TRUE) { if (!IdTCPClient1->Connected()) IdTCPClient1->Connect(); if (IdTCPClient1->Connected()) ComOk=TRUE; else { ComOk=FALSE; ResultadoCompleto="Falla la conexión"; } } else { ComOk=FALSE; ResultadoCompleto="No seleccionado Comunicate"; } /* Limpieza del buffer. En caso de haber enviado cadenas PCTrigger al Robot mientras este se encuentra en PAUSE, porque se ha pulsado STOP o bien por alguna alarma, al reiniciarse procesará y responderá a todos los PCTrigger llenando el buffer de recepción del PC de basura que el PC iría recogiendo dessincronizadamente con ReadLn. Por eso se debe vaciar al comienzo de cada secuencia */ if (ComOk){ while (IdTCPClient1->ReadLn("\r",20)!="") ContadorTramasBasura++; } /* Enviar trigger software al Robot, cadena de texto "PCTrigger" */ if (ComOk) { TramaEnviada="PCTrigger,"+AnsiString(Nciclos)+",0,0,0,0,0"; IdTCPClient1->WriteLn(TramaEnviada); StatusBarInfo->Panels->Items[3]->Text="Enviado: "+TramaEnviada; ResultadoCompleto="Enviado PCTrigger"; } /* Captura de imagen, la cámara está en modo video (default). El tiempo empleado será un error de encoder para el tracking! */ if (CheckBoxCaptura->Checked==TRUE) ActionCaptura->Execute(); /* Confirmación de respuesta del robot, cadena "ACKPCTrigger"+Nciclos */ if (ComOk) { RespuestaRobot=IdTCPClient1->ReadLn("\r",TimeoutTCP); StatusBarInfo->Panels->Items[4]->Text="Recibido: "+RespuestaRobot; if (RespuestaRobot!=("ACKPCTrigger"+AnsiString(Nciclos))) { ComOk=FALSE; ResultadoCompleto="Timeout ACKCPTrigger"; } else ResultadoCompleto="Recibido ACKPCTrigger"; } /* Procesamiento de la imagen */ if (CheckBoxUmbralOtsu->Checked==FALSE) { StaticTextTHist->Caption="His 000ms"; StaticTextTOtsu->Caption="Ots 000ms"; Ingeniería en Automática y Electrónica Industrial A1-28 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder } else ActionHistograma->Execute(); ActionBinariza->Execute(); if (CheckBoxErosion->Checked==FALSE) { StaticTextErosion->Caption="Ero 000ms"; } else ActionErosion->Execute(); ActionEtiquetado->Execute(); /* Confirmación de que hay datos que merezca la pena enviar */ int Npiezas; if (ComOk) { Npiezas=Global::GetNpiezas(); if (Npiezas==0) { ComOk=False; ResultadoCompleto="Npiezas=0, no hay datos listos"; } } Tcom=1000*(App1->Timer->Read()); /* Envio de datos de posicion si procede */ int cntpiezas=0; while ((ComOk)&& (cntpiezas<Npiezas)) { TramaEnviada= "Datos,"+ AnsiString(Nciclos)+","+ AnsiString(Global::GetXCG(cntpiezas))+","+ AnsiString(Global::GetYCG(cntpiezas))+","+ "1,"+ // Orientación, sin uso AnsiString(cntpiezas+1)+","+ AnsiString(Npiezas) ; cntpiezas++; IdTCPClient1->WriteLn(TramaEnviada); StatusBarInfo->Panels->Items[3]->Text="Enviado: "+TramaEnviada; ResultadoCompleto="Enviado hasta Pieza "+AnsiString(cntpiezas); } /* Confirmación de respuesta del robot, cadena "ACKDatos" */ if (ComOk) { RespuestaRobot=IdTCPClient1->ReadLn("\r",TimeoutTCP); StatusBarInfo->Panels->Items[4]->Text="Recibido: "+RespuestaRobot; if (RespuestaRobot!="ACKDatos") { ComOk=FALSE; ResultadoCompleto="Timeout ACKDatos"; } else ResultadoCompleto="Recibido ACKDatos"; } Tfin=1000*(App1->Timer->Read()); Ingeniería en Automática y Electrónica Industrial A1-29 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder StaticTextTCompleto->Caption="TOT "+AnsiString(Tfin-Tini)+"ms"; StaticTextTCom->Caption="Com "+AnsiString(Tfin-Tcom)+"ms"; MemoComunicaciones->Lines->Append(AnsiString(Global::GetNciclos())+": "+ ResultadoCompleto); } //--------------------------------------------------------------------------void __fastcall TForm1::ImagencirculoClick(TObject *Sender) { VARIANT vimagen; SAFEARRAY *psaimagen=NULL; SAFEARRAYBOUND rgsabound[2]; const unsigned int cDims=2; long rgIndices[2]; int SizeX,SizeY; int ValorBajo,ValorAlto; unsigned char pixelOUT; ValorBajo=0; ValorAlto=255; VariantInit(&vimagen); vimagen.vt=VT_ARRAY|VT_UI1; SizeX=ImageMil2->SizeX; SizeY=ImageMil2->SizeY; rgsabound[0].cElements=SizeX; rgsabound[0].lLbound=0; rgsabound[1].cElements=SizeY; rgsabound[1].lLbound=0; // tipo de dato: SAFEARRAY de UINT8 psaimagen=SafeArrayCreate(VT_UI1,cDims,rgsabound); vimagen.parray=psaimagen; for(int i=0;i<SizeX;i++) { for(int j=0;j<SizeY;j++) { rgIndices[0]=i; rgIndices[1]=j; pixelOUT=ValorBajo; if ( ((i-200)*(i-200)+(j-200)*(j-200))<=10000 ) pixelOUT=ValorAlto; if ( ((i-400)*(i-400)+(j-200)*(j-200))<=10000 ) pixelOUT=ValorAlto; SafeArrayPutElement(psaimagen,rgIndices,&pixelOUT); } } ImageMil1->Put(vimagen,imSingleBand,imAllBands,0,0,SizeX,SizeY); VariantClear(&vimagen); } //--------------------------------------------------------------------------void __fastcall TForm1::Cargarsobreimagendcha1Click(TObject *Sender) Ingeniería en Automática y Electrónica Industrial A1-30 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder { ImageMil2->Load(NULL,0); } //--------------------------------------------------------------------------void __fastcall TForm1::Salvarimagendcha1Click(TObject *Sender) { ImageMil2->Save(NULL); } //--------------------------------------------------------------------------void __fastcall TForm1::Imagendepruebavarioscirculos1Click(TObject *Sender) { VARIANT vimagen; SAFEARRAY *psaimagen=NULL; SAFEARRAYBOUND rgsabound[2]; const unsigned int cDims=2; long rgIndices[2]; int SizeX,SizeY; int ValorBajo,ValorAlto; unsigned char pixelOUT; ValorBajo=0; ValorAlto=255; VariantInit(&vimagen); vimagen.vt=VT_ARRAY|VT_UI1; SizeX=ImageMil2->SizeX; SizeY=ImageMil2->SizeY; rgsabound[0].cElements=SizeX; rgsabound[0].lLbound=0; rgsabound[1].cElements=SizeY; rgsabound[1].lLbound=0; // tipo de dato: SAFEARRAY de UINT8 psaimagen=SafeArrayCreate(VT_UI1,cDims,rgsabound); vimagen.parray=psaimagen; for(int i=0;i<SizeX;i++) { for(int j=0;j<SizeY;j++) { rgIndices[0]=i; rgIndices[1]=j; pixelOUT=ValorBajo; if ( ((i-200)*(i-200)+(j-200)*(j-200))<=4000 ) pixelOUT=ValorAlto; if ( ((i-400)*(i-400)+(j-350)*(j-350))<=8000 ) pixelOUT=ValorAlto; if ( ((i-500)*(i-500)+(j-350)*(j-350))<=8000 ) pixelOUT=ValorAlto; if ( ((i-100)*(i-100)+(j-450)*(j-450))<=2000 ) pixelOUT=ValorAlto; if ( ((i-600)*(i-600)+(j-100)*(j-100))<=3000 ) pixelOUT=ValorAlto; SafeArrayPutElement(psaimagen,rgIndices,&pixelOUT); } Ingeniería en Automática y Electrónica Industrial A1-31 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder } ImageMil1->Put(vimagen,imSingleBand,imAllBands,0,0,SizeX,SizeY); VariantClear(&vimagen); } //--------------------------------------------------------------------------void __fastcall TForm1::ButtonTestClick(TObject *Sender) { ActionCompletoMultiple->Execute(); } //--------------------------------------------------------------------------void __fastcall TForm1::ActionPrefiltradoMedianaExecute(TObject *Sender) { VARIANT vimagenIN,vimagenOUT; SAFEARRAY *psaimagenIN=NULL,*psaimagenOUT=NULL; SAFEARRAYBOUND rgsabound[2]; const unsigned int cDims=2; long rgIndices[2],rgIndicesEntorno[2]; int SizeX,SizeY; unsigned char pixelIN,pixelOUT; long Tini,Tfin; // long deliberadamente para casting a ms Tini=1000*(App1->Timer->Read()); /* Extracción de imagen desde ImageMil1 */ VariantInit(&vimagenIN); vimagenIN.vt=VT_ARRAY|VT_UI1; // tipo de dato: SAFEARRAY de UINT8 VariantInit(&vimagenOUT); vimagenOUT.vt=VT_ARRAY|VT_UI1; // tipo de dato: SAFEARRAY de UINT8 SizeX=ImageMil1->SizeX; SizeY=ImageMil1->SizeY; rgsabound[0].cElements=SizeX; rgsabound[0].lLbound=0; rgsabound[1].cElements=SizeY; rgsabound[1].lLbound=0; psaimagenIN=SafeArrayCreate(VT_UI1,cDims,rgsabound); psaimagenOUT=SafeArrayCreate(VT_UI1,cDims,rgsabound); vimagenIN.parray=psaimagenIN; vimagenOUT.parray=psaimagenOUT; ImageMil1->Get(&vimagenIN,imSingleBand,imAllBands,0,0,SizeX,SizeY); /*Ya tenemos la imagen en psaimagenIN, seguimos.. */ /* Asignación dinámica de memoria para matrices mascara y entorno */ int *vectorentorno,cntentorno; vectorentorno=new int[OrdenDeMascaraMediana*OrdenDeMascaraMediana]; /* Barrido de imagen */ int ipix,jpix; int pixtemp; bool FinOrdenado; int radiomascara; Ingeniería en Automática y Electrónica Industrial A1-32 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder /* Radio de la matriz mascara */ radiomascara=OrdenDeMascaraMediana/2; //ShowMessage("radiomascara="+AnsiString(radiomascara)); { for(int i=0;i<SizeX;i++) { for(int j=0;j<SizeY;j++) { rgIndices[0]=i; rgIndices[1]=j; SafeArrayGetElement(psaimagenIN,rgIndices,&pixelIN); /* Barrido de cada entorno de pixel blanco */ cntentorno=0; for (int fil=0;fil<OrdenDeMascaraMediana;fil++) { for (int col=0;col<OrdenDeMascaraMediana;col++) /* Para cada pixel del entorno */ ipix=i+fil-radiomascara; jpix=j+col-radiomascara; if ((ipix>0)&&(ipix<SizeX)&&(jpix>0)&&(jpix<SizeY)) { /* Acceso al pixel, del entorno */ cnt[9]++; rgIndicesEntorno[0]=ipix; rgIndicesEntorno[1]=jpix; SafeArrayGetElement(psaimagenIN, rgIndicesEntorno,&pixelIN); vectorentorno[cntentorno]=pixelI N; cntentorno++; } } } /* Ordenado de entorno para tomar mediana */ FinOrdenado=0; while (!FinOrdenado) { FinOrdenado=1; for (int e=0;e<cntentorno-1;e++) { if (vectorentorno[e]>vectorentorno[e+1]) { pixtemp=vectorentorno[e]; vectorentorno[e]=vectorentorno[e +1]; vectorentorno[e+1]=pixtemp; FinOrdenado=0; } } } /* Ahora se toma la mediana */ pixelOUT=vectorentorno[cntentorno/2+1]; SafeArrayPutElement(psaimagenOUT,rgIndices,&pixelOUT); } } /* Ya tenemos la imagen erosionada en psaimagenOUT */ ImageMil1->Put(vimagenOUT,imSingleBand,imAllBands,0,0,SizeX,SizeY); Ingeniería en Automática y Electrónica Industrial A1-33 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder delete [] vectorentorno; VariantClear(&vimagenIN); VariantClear(&vimagenOUT); Tfin=1000*(App1->Timer->Read()); StaticTextMediana->Caption="Fil "+AnsiString(Tfin-Tini)+"ms"; } //--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender) { ActionPrefiltradoMediana->Execute(); } //--------------------------------------------------------------------------- A1.3 Código fuente Unit1_VisionV7.h //--------------------------------------------------------------------------#ifndef Unit1_VisionV7H #define Unit1_VisionV7H //--------------------------------------------------------------------------#include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include "MIL_OCX.h" #include <OleCtrls.hpp> #include <ExtCtrls.hpp> #include <Chart.hpp> #include <Series.hpp> #include <TeEngine.hpp> #include <TeeProcs.hpp> #include <IdBaseComponent.hpp> #include <IdComponent.hpp> #include <IdTCPClient.hpp> #include <IdTCPConnection.hpp> #include <IdAntiFreeze.hpp> #include <IdAntiFreezeBase.hpp> #include <Grids.hpp> #include <ValEdit.hpp> #include <Menus.hpp> #include <ActnList.hpp> #include <Buttons.hpp> #include <ComCtrls.hpp> //--------------------------------------------------------------------------class TForm1 : public TForm { __published: // IDE-managed Components TApp *App1; TSYSTEM *SYSTEM1; TDigitizer *Digitizer1; TImageMil *ImageMil1; Ingeniería en Automática y Electrónica Industrial A1-34 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder TDisplay *Display1; TButton *ButtonGrab; TButton *ButtonGrabCont; TGraphicContext *GraphicContext1; TDisplay *Display2; TImageMil *ImageMil2; TButton *ButtonBinariza; TScrollBar *ScrollBarUmbral; TButton *ButtonExit; TChart *ChartHistograma; TBarSeries *Series1; TStaticText *StaticTextUmbral; TButton *ButtonHistograma; TButton *ButtonCG; TIdTCPClient *IdTCPClient1; TIdAntiFreeze *IdAntiFreeze1; TTimer *TimerInfo; TMainMenu *MainMenu1; TMenuItem *ArchivoImagen; TMenuItem *Cargar; TMenuItem *Salvar; TStaticText *StaticTextTGrab; TStaticText *StaticTextTHist; TStaticText *StaticTextTOtsu; TStaticText *StaticTextTCG; TStaticText *StaticTextTBin; TMenuItem *HerramientasVision; TMenuItem *Histogramapasoapaso; TMenuItem *Otsupasoapaso; TLineSeries *Series2; TMenuItem *Imagenizdadcha; TMenuItem *Invierteimagendcha; TMenuItem *Imagenpruebasimple; TStaticText *StaticTextMedia; TStaticText *StaticTextVarMax; TMenuItem *HerramientasRobot; TMenuItem *EnviaceroaRobot; TMenuItem *Conectar; TButton *ButtonStart; TButton *ButtonStop; TTimer *TimerRun; TActionList *ActionList1; TAction *ActionCaptura; TAction *ActionHistograma; TAction *ActionBinariza; TAction *ActionBusqueda; TAction *ActionCompleto; TSpeedButton *SpeedButtonManual; TSpeedButton *SpeedButtonAuto; TButton *ButtonStart1Ciclo; TStaticText *StaticTextTCompleto; TMenuItem *EnviaXYalRobot1; TStaticText *StaticTextTCom; TLineSeries *Series3; TCheckBox *CheckBoxComunicate; TCheckBox *CheckBoxGrafica; TMenuItem *Desconectar; TButton *ButtonErosion; Ingeniería en Automática y Electrónica Industrial A1-35 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder TStaticText *StaticTextErosion; TAction *ActionErosion; TAction *ActionEtiquetado; TStaticText *StaticTextEtiquetado; TButton *ButtonEtiqueta; TMemo *MemoEtiquetado; TAction *ActionCompletoMultiple; TCheckBox *CheckBoxColorea; TMenuItem *Imagencirculo; TMenuItem *Cargarsobreimagendcha1; TMenuItem *Salvarimagendcha1; TMenuItem *Imagendepruebavarioscirculos1; TCheckBox *CheckBoxCaptura; TBevel *Bevel2; TBevel *Bevel4; TCheckBox *CheckBoxUmbralOtsu; TCheckBox *CheckBoxErosion; TStatusBar *StatusBarInfo; TMemo *MemoComunicaciones; TAction *ActionPrefiltradoMediana; TCheckBox *CheckBoxMediana; TButton *Button1; TStaticText *StaticTextMediana; void __fastcall ButtonGrabClick(TObject *Sender); void __fastcall ButtonGrabContClick(TObject *Sender); void __fastcall ButtonHaltClick(TObject *Sender); void __fastcall ButtonCopiaClick(TObject *Sender); void __fastcall ButtonInvertClick(TObject *Sender); void __fastcall ScrollBarUmbralChange(TObject *Sender); void __fastcall FormCreate(TObject *Sender); void __fastcall ButtonBinarizaClick(TObject *Sender); void __fastcall ButtonExitClick(TObject *Sender); void __fastcall ImageMil1ContentModified(TObject *Sender, long OffsetX, long OffsetY, long SizeX, long SizeY); void __fastcall ButtonHistogramaClick(TObject *Sender); void __fastcall ButtonCGClick(TObject *Sender); void __fastcall IdTCPClient1Connected(TObject *Sender); void __fastcall IdTCPClient1Disconnected(TObject *Sender); void __fastcall ButtonConnectClick(TObject *Sender); void __fastcall ButtonDisconnectClick(TObject *Sender); void __fastcall ButtonWriteClick(TObject *Sender); void __fastcall ButtonReadClick(TObject *Sender); void __fastcall TimerInfoTimer(TObject *Sender); void __fastcall LabeledEditOnChange(TObject *Sender); void __fastcall Digitizer1CameraPresent(TObject *Sender); void __fastcall ButtonEtiquetadoClick(TObject *Sender); void __fastcall CargarClick(TObject *Sender); void __fastcall SalvarClick(TObject *Sender); void __fastcall HistogramapasoapasoClick(TObject *Sender); void __fastcall OtsupasoapasoClick(TObject *Sender); void __fastcall ImagenizdadchaClick(TObject *Sender); void __fastcall InvierteimagendchaClick(TObject *Sender); void __fastcall ImagenpruebasimpleClick(TObject *Sender); void __fastcall EnviaceroaRobotClick(TObject *Sender); void __fastcall ConectarClick(TObject *Sender); void __fastcall ButtonStartClick(TObject *Sender); void __fastcall ButtonStopClick(TObject *Sender); void __fastcall ActionHistogramaExecute(TObject *Sender); Ingeniería en Automática y Electrónica Industrial A1-36 Integración de sistema de visión artificial y robot en aplicación tipo Pick&Place A1 Listado de programas de C++ Builder void __fastcall ActionCapturaExecute(TObject *Sender); void __fastcall ActionBusquedaExecute(TObject *Sender); void __fastcall ActionBinarizaExecute(TObject *Sender); void __fastcall TimerRunTimer(TObject *Sender); void __fastcall SpeedButtonManualClick(TObject *Sender); void __fastcall SpeedButtonAutoClick(TObject *Sender); void __fastcall ButtonStart1CicloClick(TObject *Sender); void __fastcall ActionCompletoExecute(TObject *Sender); void __fastcall EnviaXYalRobot1Click(TObject *Sender); void __fastcall DesconectarClick(TObject *Sender); void __fastcall ActionErosionExecute(TObject *Sender); void __fastcall ButtonErosionClick(TObject *Sender); void __fastcall ActionEtiquetadoExecute(TObject *Sender); void __fastcall ButtonEtiquetaClick(TObject *Sender); void __fastcall ActionCompletoMultipleExecute(TObject *Sender); void __fastcall ImagencirculoClick(TObject *Sender); void __fastcall Cargarsobreimagendcha1Click(TObject *Sender); void __fastcall Salvarimagendcha1Click(TObject *Sender); void __fastcall Imagendepruebavarioscirculos1Click( TObject *Sender); void __fastcall ButtonTestClick(TObject *Sender); void __fastcall ActionPrefiltradoMedianaExecute(TObject *Sender); void __fastcall Button1Click(TObject *Sender); private: public: // User declarations // User declarations __fastcall TForm1(TComponent* Owner); }; //--------------------------------------------------------------------------extern PACKAGE TForm1 *Form1; //--------------------------------------------------------------------------#endif Ingeniería en Automática y Electrónica Industrial A1-37