Recentemente, uma amiga minha me pediu um exemplo de como exibir um video carregado pelo OpenCV utilizando o FOX.Entao eu rapidamente fiz um programinha para ajuda-la: um micro-player de video. Micro porque nao faz nada alem de exibir os quadros. Sem som (OpenCV nao trabalha com som). Sem controles, nem nada. Abriu o video e pronto.Obs.: Este topico, assim como os outros relacionados ao OpenCV, sao direcionados aqueles que ja tem experiencia com o FOX Toolkit, especialmente este aqui por conter itens que ainda nao tratei. Tratarei todos esses assuntos em topicos futuros.Bom, vamos la.FoxVideoPlayerMainWindow.hDeclaracao dos objetosFXImage *image;Esta e a imagem que sera desenhada no canvas (area de desenho), representando cada quadro do video.FXCanvas *canvas;Esta e a area de desenho propriamente dita.CvCapture *capture;Uma estrutura sinistra que o OpenCV utiliza para guardar as informacoes do video sendo capturado. Sinistra porque a documentacao nao revela a estrutura interna. Para conhece-la, e preciso ir no fonte do OpenCV, coisa que eu ainda nao quis fazer.IplImage *frame;Cada quadro do video e uma IplImage. Precisa dizer mais?double freq;Frequencia de atualizacao. E um video, nao e? Nao pode ficar no mesmo quadro para sempre.IplImage *dummy;Essa e uma pseudo-imagem apenas para converter os quadros para a representacao interna do FOX, conforme discutido aqui.EventosExistem apenas tres eventos: pintar o canvas, carregar um video e pegar o proximo quadro. Assim:public: enum { ID_CANVAS = FXMainWindow::ID_LAST, ID_LOAD_VIDEO, ID_FRAME, }; /* Pintar o canvas */ long onPaintCanvas(FXObject*, FXSelector, void*); /* Carregar o video */ long onCmdLoadVideo(FXObject*, FXSelector, void*); /* Pegar cada quadro do video */ long onTimeoutFrame(FXObject*, FXSelector, void*);E e isso. Agora, vamos implementar essa cambada.FoxVideoPlayerMainWindow.cppConstrutor da janelaFoxVideoPlayerMainWindow::FoxVideoPlayerMainWindow(FXApp *a) : FXMainWindow(a, "FoxVideoPlayer", 0, 0, DECOR_ALL) { FXToolBar *toolBar = new FXToolBar(this, this); new FXButton(toolBar, "Abrir video", 0, this, ID_LOAD_VIDEO, BUTTON_NORMAL|BUTTON_TOOLBAR); canvas = new FXCanvas(this, this, ID_CANVAS, LAYOUT_FIX_WIDTH|LAYOUT_FIX_HEIGHT, 0, 0, 0, 0); image = 0; capture = 0; frame = 0; dummy = 0;}Aqui eu simplesmente crio uma barra de ferramentas com um botao para carregar um video, crio o canvas e inicializo os demais objetos com nulo. Nada de mais.Pintando o canvaslong FoxVideoPlayerMainWindow::onPaintCanvas(FXObject*, FXSelector, void *ptr) { FXEvent *ev = static_cast<FXEvent*>(ptr); FXDCWindow dc(canvas, ev); if (frame) { dc.drawImage(image, 0, 0); } else { dc.setForeground(FXRGB(0, 0, 0)); dc.fillRectangle(0, 0, canvas->getWidth(), canvas->getHeight()); } return 1;}Duas opcoes: se houver um quadro a desenhar, desenha. Senao, desenha um retangulo preto. Simples.Carregando o videoEssa funcao e um pouco grande, entao vou quebra-la em algumas partes.long FoxVideoPlayerMainWindow::onCmdLoadVideo(FXObject*, FXSelector, void*) { FXFileDialog dialog(this, "Abrir video"); dialog.setDirectory(FXSystem::getHomeDirectory()); if (!dialog.execute(PLACEMENT_OWNER)) return 1; FXString filename = dialog.getFilename();Exibe uma caixa de dialogo para selecionar o video. capture = cvCaptureFromFile(filename.text()); if (!capture) { FXMessageBox::error(this, MBOX_OK, "Erro", "Erro ao abrir o video"); return 1; }Abre o video e armazena na estrutura obscura. Um erro e a funcao cvCaptureFromFile() retorna nulo. int width = (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH); int height = (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT); freq = cvGetCaptureProperty(capture, CV_CAP_PROP_FPS); freq = 1.0 / freq * 1000.0;Eu preciso saber as dimensoes do video e o numero de quadros por segundo. A funcao cvGetCaptureProperty() fornece diversas informacoes sobre o video. As informacoes disponiveis sao descritas na documentacao do OpenCV.Entretanto, e preciso fazer esse