7 11 2014
Tirando fotos com a WebCam em C#
O maior patrimônio de um site é o seu público. Por causa disso, eu sempre costumo ouvir o meu público na hora de decidir os temas dos artigos que eu publico aqui no blog. Sempre que uma nova pessoa se inscreve na minha newsletter, eu mando um e-mail de boas-vindas onde eu aproveito para fazer algumas questões básicas. Uma delas é: “Quais tópicos você gostaria que fossem abordados em posts futuros?“. A maioria das pessoas não responde esse e-mail de boas-vindas (não sei por que), mas, alguns leitores acabam respondendo.
O tema do artigo de hoje foi inspirado em uma resposta para essa pergunta, vinda de uma pessoa que se inscreveu na semana passada. A sugestão do inscrito era que eu mostrasse como tirar fotos com a webcam em C# e salvá-las em um banco de dados. Como esse é um tema muito grande, vou dividi-lo em duas partes. Nessa primeira parte, vou mostrar como tirar fotos com a webcam em C# e salvá-las no disco (e não no banco de dados). Em um artigo futuro eu vou expandir esse assunto e mostrar como salvar essas fotos em um banco de dados (EDIT: Já escrevi a extensão desse artigo mostrando como salvar as imagens no banco de dados – confira aqui).
Sempre que vou escrever um artigo, obviamente eu começo pela pesquisa sobre o tema. Acredito que não é necessário explicar que eu não sei de cabeça todos os temas dos artigos que eu publico. Por exemplo, quando eu recebi essa questão, eu não tinha nem ideia de como fazer para acessar a webcam através do C#, muito menos como tirar fotos com a webcam! Eu imaginava que provavelmente o Windows tinha uma API para acessar a webcam, mas, que um wrapper para essa API não estaria disponível direto no .NET Framework. E o meu palpite estava correto.
Depois de pesquisar um bom tempo sobre esse tema, encontrei vários artigos, threads em fóruns, etc., como estes:
- WebCam Sample
- How to preview video from a webcam (XAML)
- EasyWebCam Library and Example
- C# capturing image from webcam
- Get image from webcam
- How to use a web cam in C# with .NET Framework 4.0 and Microsoft Expression Encoder 4
- DirectShowNet library
- DirectShow .NET
- AForge.NET
- Media Foundation SDK Samples
- How to easily record from a webcam in C#
- Capture Sample with DirectX and .NET
Logo de cara já deu para perceber que a única solução seria utilizar alguma biblioteca que implementa um wrapper para as chamadas nativas. A dúvida que ficou foi: qual biblioteca utilizar? Vendo as respostas para as questões relacionadas a esse tema no StackOverflow, percebi que as melhores candidatas seriam as bibliotecas AForge.NET e DirectShow.NET. Ao analisar os websites dessas bibliotecas, a AForge.NET foi mais animadora, uma vez que o último release dela (lançado em Julho de 2013) é bem mais atual do que o último release do DirectShow.NET (lançado em Fevereiro de 2010!). Portanto, resolvi começar minha análise com ela.
Tirando fotos com a webcam utilizando a biblioteca AForge.NET – primeira tentativa
Logo que decidi analisar a biblioteca AForge.NET, fui direto à página de downloads da biblioteca para ver se já não existia um exemplo pronto dessa funcionalidade. Utilizei a opção “Download Full ZIP Archive” e fui verificar o conteúdo. Dentro da pasta “Samples/Video” encontrei um excelente candidato, o exemplo “Snapshot Maker“:
Rapidamente abri o projeto de exemplo e executei para ver o que acontecia:
Notaram a minha cara de confuso? Pois é. O ComboBox “Snapshot resolution” mostrava “Not supported“, e o botão de “Trigger” (que deveria ser o botão para tirar a bendita foto) estava desabilitado. Depois de tentar algumas gambiarras (envolvendo até adicionar manualmente alguns itens no ComboBox de resoluções para a snapshot até habilitar o botão de “Trigger” “na raça“), me convenci de que a funcionalidade de foto desse exemplo não funcionaria com a minha webcam.
Parti para uma busca mais aprofundada na Internet e acabei encontrando esta thread no fórum da biblioteca AForge.NET e mais algumas outras referências que não me recordo. Para mim ficou claro: a funcionalidade de snapshot da biblioteca AForge.NET não funcionaria com a minha webcam, porque ela não tem um botão físico para tirar foto (o que é obvio, porque é a webcam integrada do meu laptop). Como a maioria das webcams hoje em dia são integradas no próprio dispositivo e não tem botão para tirar foto, resolvi abandonar essa biblioteca e analisar a segunda opção, a biblioteca DirectShow.NET. Porém, não percam a esperança com a biblioteca AForge.NET. Depois de mais algumas investigações, consegui também fazer funcionar com ela (confira mais pra frente no artigo).
Tirando fotos com a webcam utilizando a biblioteca DirectShow.NET
Minha estratégia com a biblioteca DirectShow.NET foi a mesma utilizada com a biblioteca AForge.NET. Fui à página de exemplos da biblioteca, dei uma olhada na lista de exemplos e, pelas descrições, não encontrei nenhum que pudesse ser útil. Mas, mesmo assim, resolvi baixar o pacote com todos os exemplos para ver se eu encontrava algo que eu pudesse utilizar.
Explorando a lista de exemplos, acabei encontrando um que parecia interessante. Ele se chama “DxSnap“, e encontra-se dentro da pasta “Samples/Capture“:
Veja o readme desse exemplo:
Use DirectShow to take snapshots from the Still pin of a capture device. Note the MS encourages you to use WIA for this, but if you want to do in with DirectShow and C#, here’s how.
Pareceu interessante, então, resolvi testar. E não é que o exemplo implementava exatamente o que eu estava procurando? Agora eu só tinha que entender o que estava por trás desse código e implementá-lo de maneira mais simples.
Comecei criando uma nova solução do tipo “Windows Forms Application” e adicionando um PictureBox e um Button no Form1, que tinha sido criado automaticamente pelo Visual Studio. Dei o nome de “webCamPictureBox” para o PictureBox e “clickButton” para o Button, além de configurar o texto do Button para “Click“:
Então, quando analisei melhor o código do Form do exemplo, vi que ele parecia aparentemente bem simples. Só que ao analisar mais a fundo, percebi que ele estava utilizando uma classe chamada “Capture“, que tinha nada mais nada menos do que 537 linhas de código! Ou seja, ficou simplesmente impossível refatorar esse código para deixa-lo mais simples. Teremos que utilizar essa classe “Capture” na nossa aplicação também. Fico me perguntando o porquê de essa classe não ter sido incorporada à própria biblioteca, mas, enfim, deixa pra lá. Você pode baixar essa classe do exemplo que indiquei anteriormente ou, para facilitar a sua vida, estou disponibilizando um link para uma cópia dessa classe aqui.
Descompacte esse arquivo zip e adicione a classe “Capture.cs” ao projeto. Feito isso, baixe a última versão da biblioteca DirectShow.NET e descompacte-a em alguma pasta do seu disco rígido. Finalmente, adicione uma referência à biblioteca no seu projeto Windows Forms.
Agora vamos ao código para carregar a imagem da webcam no PictureBox. Vá até o code-behind do Form1, declare um atributo do tipo “DirectShowLib.Capture” com o nome “_camera” e adicione o código abaixo para inicializar a classe “Capture” no construtor de Form1:
private DirectShowLib.Capture _camera; public Form1() { InitializeComponent(); // Considerar a primeira câmera que for encontrada no sistema const int VIDEODEVICE = 0; // Resolucao de 640x480, 24 bits por pixel. A sua câmera tem que suportar essa resolução, senão, altere para uma resolução suportada. const int VIDEOWIDTH = 640; const int VIDEOHEIGHT = 480; const int VIDEOBITSPERPIXEL = 24; _camera = new DirectShowLib.Capture(VIDEODEVICE, VIDEOWIDTH, VIDEOHEIGHT, VIDEOBITSPERPIXEL, webCamPictureBox); }
Com isso, só falta adicionar o código para tirar a foto quando o usuário no botão “Click“. Adicione então o handler para o evento “Click” do botão e utilize o seguinte código:
private void clickButton_Click(object sender, EventArgs e) { var bitmap = new Bitmap(webCamPictureBox.Width, webCamPictureBox.Height); using (var graphics = Graphics.FromImage(bitmap)) { var webCamPoint = webCamPictureBox.PointToScreen(new Point(0, 0)); graphics.CopyFromScreen(webCamPoint.X, webCamPoint.Y, 0, 0, bitmap.Size); } bitmap.Save("snapshot.png", System.Drawing.Imaging.ImageFormat.Png); }
O código acima faz com que um arquivo chamado “snapshot.png” seja salvo no mesmo diretório do aplicativo assim que o usuário clica no botão. Note que precisei fazer uma certa gambiarra para pegar o Bitmap da imagem sendo exibida no PictureBox, uma vez que a forma com que o DirectShow.NET exibe a webcam no PictureBox é tão esquisita que ao acessar a propriedade Image ela retorna sempre null!
Para finalizar o exemplo com a biblioteca DirectShow.NET, precisamos adicionar um código que irá “matar” a instância da classe “Capture” quando o Form1 morrer, caso contrário uma exception é lançada ao fechar o Form. Para fazer isso, vamos dar um override no método OnClosed do Form1 e chamar o Dispose da câmera antes de fechar o Form:
protected override void OnClosed(EventArgs e) { _camera.Dispose(); base.OnClosed(e); }
Execute o projeto e faça um teste você mesmo.
Já em outro ambiente, outro óculos e barba mais curta. Pra vocês verem como demora escrever um artigo desses.. ;)
Tirando fotos com a webcam utilizando a biblioteca AForge.NET – segunda tentativa
Eu não fiquei convencido de que não seria possível construir esse exemplo com a biblioteca AForge.NET. Ela me parecia tão mais profissional que a DirectShow.NET, como é que ela não suportaria fazer a mesma coisa?
Parei para pensar melhor e me lembrei que alguém aqui no escritório tinha desenvolvido uma funcionalidade que utilizava a webcam, e eu estava quase certo de que tinham utilizado a biblioteca AForge. Procurei o código no nosso repositório e acabei encontrando. Dando uma olhada nos comentários, acabei descobrindo que o código foi baseado neste artigo. [Desculpe, mas, o artigo é em alemão. Aliás, aqui cabe um parêntese: durante a sua vida, aprenda a maior quantidade de idiomas que você conseguir! Cada idioma que você aprende é mais uma possibilidade de você encontrar respostas no Google de maneira mais rápida!]. Olhando melhor no fórum da AForge.NET, encontrei esta thread, onde a pessoa que respondeu disse que quase nenhuma câmera suporta snapshot nativamente, e que ele utilizaria o evento que retorna o frame atual para tirar uma snapshot (justamente o que aquele artigo em alemão mostra).
Então eu estava decidido. Queria fazer com que o mesmo exemplo funcionasse também com a biblioteca AForge.NET. Vamos ajustá-lo juntos?
Primeiramente, faça o download da biblioteca (libraries only) e adicione referências às dlls “AForge.Video.dll” e “AForge.Video.DirectShow.dll“. Feito isso, adicione um outro Form ao projeto (Form2) e copie o mesmo layout que utilizamos no exemplo da biblioteca DirectShow.NET (um PictureBox para mostrar a imagem da webcam e um Button para tirar a foto). Depois, vá até o code-behind do Form2 e adicione uma instância da classe AForge.Video.DirectShow.VideoCaptureDevice, além do código para inicializa-la no construtor do Form:
AForge.Video.DirectShow.VideoCaptureDevice videoSource; public Form2() { InitializeComponent(); AForge.Video.DirectShow.FilterInfoCollection videosources = new AForge.Video.DirectShow.FilterInfoCollection(AForge.Video.DirectShow.FilterCategory.VideoInputDevice); if (videosources != null) { videoSource = new AForge.Video.DirectShow.VideoCaptureDevice(videosources[0].MonikerString); videoSource.NewFrame += (s, e) => { if(webCamPictureBox.Image != null) { webCamPictureBox.Image.Dispose(); } webCamPictureBox.Image = (Bitmap)e.Frame.Clone(); } videoSource.Start(); } }
Além disso, precisamos também adicionar o código no evento “Click” do botão para tirar a foto e salvar no arquivo “snapshot.png“. Dessa vez não é preciso nenhuma gambiarra, uma vez que a propriedade Image do PictureBox já retorna a imagem sendo exibida no momento, bastando apenas salvá-la em disco:
private void clickButton_Click(object sender, EventArgs e) { webCamPictureBox.Image.Save("snapshot.png", System.Drawing.Imaging.ImageFormat.Png); }
Por fim, com a biblioteca AForge.NET também precisamos desligar a câmera antes de fechar o Form, senão uma exception também é lançada. Para isso, faça um override do método OnClosed e adicione o seguinte código para matar a câmera antes de fechar o Form:
protected override void OnClosed(EventArgs e) { base.OnClosed(e); if (videoSource != null && videoSource.IsRunning) { videoSource.SignalToStop(); videoSource = null; } }
E com isso conseguimos implementar exatamente a mesma funcionalidade utilizando a biblioteca AForge.NET, que é muito mais limpa, moderna e fácil de utilizar do que a DirectShow.NET.
Concluindo
Tirar fotos com a webcam em C# não é uma tarefa fácil à primeira vista. É uma tarefa praticamente impossível de ser realizada sem a utilização de bibliotecas para acessar a webcam. As melhores bibliotecas para o .NET que eu encontrei na minha pesquisa foram a AForge.NET e a DirectShow.NET. Ambas dão conta do recado, mas, preferi a AForge.NET, porque ela é mais moderna, aparentemente mais profissional e o código fica mais limpo (apesar de eu não ter conseguido fazer funcionar na primeira tentativa).
Nessa primeira parte sobre a utilização da webcam com C#, mostrei como acessar a câmera, tirar uma foto e armazená-la em um caminho fixo em disco. Em um próximo artigo no futuro (que muito provavelmente não será na próxima semana), vou finalizar a dúvida do inscrito e mostrar como expandir esse exemplo para salvar a foto em um banco de dados.
E você, já teve alguma experiência com a webcam no .NET? Você utilizou uma dessas duas bibliotecas ou utilizou alguma outra? Conte-me mais sobre as suas experiências logo abaixo nos comentários. E, caso você ainda não tenha se inscrito, convido para que você se inscreva na minha newsletter. Como você pode perceber, eu sempre ouço os meus inscritos e publico artigos de interesse deles. O que você está esperando para se inscrever?
Até o próximo artigo!
André Lima
Image by Hannaford used under Creative Commons
https://www.flickr.com/photos/27745117@N00/2051506962/
Exibindo uma imagem a partir de um caminho em disco no Report Viewer Deu a louca na Microsoft: .NET Framework open source e Visual Studio de graça?
Fala André, blz?
Um dia eu chego nesse nível de escrita hehe Ficou muito bem explicado o conteúdo. Eu nunca precisei usar uma funcionalidade desse tipo, mas, assim que eu chegar em casa vou dar uma brincada com a webcam :)
Parabéns!
Abraços.
Wennder Santos
Ahh Wennder! Por que? Sua escrita é de alto nível, poxa!
Valeu pelo comentário!
Abraco!
André Lima
muito legal, parabens pelo post, fiz aqui com a AForge.NET e ficou perfeito consegui aplicar no meu sistema.
Olá Arimateia, obrigado pelo comentário! Fico feliz que você tenha conseguido aplicar essa dica no seu projeto!
Abraço!
André Lima
Oi André, top o artigo em! Aqui na agência precisei fazer algo parecido para web, se naquela epoca tivesse um artigo bom quanto esse, eu teria feito de forma muito mais fácil.
Olá Edison!
Muito obrigado pelo comentário! Pena que você não pôde aproveitar esse artigo antes quando você estava precisando.. Mas, pelo menos agora fica aqui para outras pessoas que precisarem no futuro.. ;)
Abraço!
André Lima
André, muito bom cara Parabéns!
Queria saber de voce como que eu defino o tamanho da imagem da webcam, para ela se adequar ao tamanho do meu picturebox. Quando aparece a imagem da webcam eu tenho que colocar o picturebox do tamanho da tela do meu computador para ver o tamanho real da minha webcam.
obrigado
Olá Rafael, obrigado pelo comentário!
Imagino que você esteja utilizando o exemplo com a biblioteca AForge, certo? Porque com a biblioteca DirectShowNet, a resolução da captura é configurada através das constantes VIDEOWIDTH e VIDEOHEIGHT.. Já no AForge, para configurar a resolução, você deve analisar o conteúdo da lista de VideoCapabilities da variável videoSource.. Nessa lista estão todas as resoluções suportadas pela sua webcam.. Para configurar uma resolução específica, basta setar a propriedade VideoResolution da variável videoSource (antes de chamar o método Start).. Por exemplo:
videoSource.VideoResolution = videoSource.VideoCapabilities[1];
videoSource.Start();
Isso fará com que a resolução seja alterada para o que está definido da VideoCapability “1” da webcam.. No caso da minha webcam, essa resolução é 1024×768..
Agora, caso você queira que a PictureBox se ajuste automaticamente independente da resolução da webcam, basta configurar a propriedade “SizeMode” da PictureBox para “Zoom”.. Dessa forma a imagem será automaticamente redimensionada para ocupar todo o espaço da PictureBox, independente da resolução utilizada pela webcam..
Espero que essa dica te ajude.. E, caso queira ficar por dentro de todas as novidades aqui do blog, inscreva-se na minha newsletter..
Abraço!
André Lima
[…] motivo pelo qual eu escolhi esse tema foi que, algumas semanas atrás, eu escrevi um artigo no meu blog sobre o acesso à webcam em C# (para aplicativos desktop, não Windows Store). Se vocês conferirem o artigo, vocês perceberão […]
[…] ideia básica é estender o artigo sobre fotos com a webcam no C# que foi publicado em Novembro de 2014. Portanto, após ter criado o projeto Windows Forms, ajuste o […]
Excelente tutorial, infelizmente, utilizando o aforge, não consegui salvar a imagem, clico no botão click e nada acontece. Como fazer?
Olá Gilberto, obrigado pelo comentário!
Muito estranho esse comportamento. Você tem certeza que associou o event handler ao evento “Click” do botão (na janela de propriedades, seção “eventos”)? Se você colocar um breakpoint na primeira linha do método correspondente ao clique do botão, executar a aplicação e clicar no botão, o breakpoint é acionado?
Abraço!
André Lima
Olá, Boa noite!
Muitíssimo interessante seu post, consegui fazer sem nem me esforçar. Mas eu preciso ir além disso se voce pudesse ajudar-me….
Como salvar a imagem em um tamanho diferente do que esta programado voce sabe?
Tipo um tamanho bem pequeno sememlhante a uma foto 3×4
Olá Edivan, obrigado pelo comentário! Fico feliz que tenha gostado do post!
Quanto ao redimensionamento da imagem, esse foi um desafio que também passei quando estava desenvolvendo essa funcionalidade para o sistema da empresa onde eu trabalho.. Utilizamos o método “ResizePic” que você encontra neste link (está em alemão, mas, dá pra entender o que o código faz):
http://dotnet-snippets.de/snippet/groesse-eines-bildes-mit-mit-gleichem-seitenverhaeltniss-aendern/837
Aí você consegue reduzir a imagem da seguinte forma (onde “maxWidth” é o comprimento máximo que você quer considerar – nesse caso 200 pixels):
Image pictureBitmap = new Bitmap(pictureStream);
double maxWidth = 200;
var widthRatio = maxWidth / (double)pictureBitmap.Width;
Image reducedPicture = ResizePic(pictureBitmap, maxWidth, Convert.ToInt32(pictureBitmap.Height * widthRatio), false, Color.Transparent, -1, -1);
var reducedPictureStream = new MemoryStream();
reducedPicture.Save(reducedPictureStream, System.Drawing.Imaging.ImageFormat.Png);
É isso aí. Espero que te ajude!
Abraço!
André Lima
André, parabéns cara!
Seu artigo é divertido e muito didatico. Consegui utilar o seu exmplo na minha aplicação, ajudou muito.
valeu!
Olá Tiago!
Muito obrigado pelo comentário! Fico feliz que você tenha gostado do artigo e que ele tenha te ajudado!
Abraço!
André Lima
Boa tarde,
muito bom, gostei do post, bem explicado, foi de grande ajuda.
Mas notei que ao utilizar o “DirectShow.NET” na chamada do evento do botão, você utiliza o graphics.CopyFromScreen(). Ele está tirando um print da tela do seu computador, percebi isso enquanto debugava.
A Classe Capture tem um método Click() que retorna um IntPtr, que posso passar no construtor do Bitmap();
o meu ficou assim
var img = this.Capture.Click();
var bitmap = new Bitmap(this.Capture.Width, this.Capture.Height, this.Capture.Stride, PixelFormat.Format24bppRgb , img);
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
bitmap.Save("teste.png", ImageFormat.Png);
abraços!
Olá Felippe, obrigado pelo comentário!
Estranho.. Quando desenvolvi o exemplo ele só copiou a imagem, e não a tela do computador.. Mas, de qualquer forma, muito obrigado por ter postado a alternativa que você acabou utilizando para contornar esse problema!
Um grande abraço!
André Lima
Muito Bom Obrigado pela dica, funcionou perfeito, só falta agora um meio de pegar fotos da câmera em alta definição, a minha C920 tem 3mega pixel real mas só estou conseguindo capturar 640x480px…
Olá Ricardo, obrigado pelo comentário!
Qual das duas bibliotecas você acabou utilizando? Com o AForge você tem que alterar o VideoResolution para a Capability que corresponde à resolução que você quer.. Pesquise por “resolução” aqui neste artigo que você vai encontrar outros comentários onde eu mencionei isso..
Se você já tentou alterar essa propriedade, estranho só estar pegando em 640×480.. Sempre consegui tirar as fotos em alta resolução nos computadores onde eu testei.. Pode ser que seja alguma coisa relacionada ao driver que não está expondo todas as resoluções.. A câmera funciona com outras resoluções em outros softwares de captura?
Abraço!
André Lima
Estou usando a DirectShowLib, mas sempre que coloco resolução acima 800×600 da erro nem inicia, tenho uma C920 da logitech mas tentei com outra webcam e continuou mesma coisa, mas no final acabei usando o próprio software da logitech e diz apenas um outro para mover o cursor em cima do botão disparar e simular um click de mouse… não ficou uma solução elegante mas resolveu meu problema de fazer fotos sequenciais.. Eu também havia tentado a AForge mas também dava erro ao iniciar com resolução acima de 800×600. Obrigado pela ajuda.
Olá Ricardo!
Interessante.. Se algum dia você descobrir uma alternativa melhor ou até mesmo o motivo desse erro, não esquece de voltar aqui pra contar pra gente..
Abraço!
André Lima
Boa noite! Muito obrigado por compartilhar seu conhecimento conosco. Consegui sem muito esforço tirar a foto. Embora gostaria de fazer duas coisas que não consegui fazer.
1. Quando tira a foto gostaria que a imagem ficasse paralisada no local que esta aparecendo a imagem da câmera em movimento.
2. Toda vez que tira uma foto nova, ela sobrescreve a anterior no arquivo snapshot.
É possivel que a foto fique parada logo após o clique no botão? e é possivel não sobrescrever o arquivo da foto, e sim armazenar todas as fotos que foram tiradas??
Muito obrigado pela ajuda.
Olá Gustavo, obrigado pelo comentário! Fico feliz que o artigo tenha te ajudado..
Quanto às suas questões.. Supondo que você tenha utilizado a biblioteca AForge (que é a opção mais fácil de utilizar), para que a foto fique paralisada, basta você chamar um “SignalToStop” no videoSource após ter salvo a imagem:
private void clickButton_Click(object sender, EventArgs e)
{
webCamPictureBox.Image.Save(“snapshot.png”, System.Drawing.Imaging.ImageFormat.Png);
videoSource.SignalToStop();
}
Depois, quando você quiser que a camera volte a funcionar, basta chamar um “Start” no videoSource.. Por exemplo, digamos que você queira fazer a camera voltar a funcionar se você clicar na PictureBox:
private void webCamPictureBox_Click(object sender, EventArgs e)
{
videoSource.Start();
}
Já a questão de salvar todas as fotos ao invés de sobrescrever, você tem algumas opções.. Uma delas é utilizar um contador e utilizá-lo no nome do arquivo.. Dessa forma você teria os arquivos snapshot-1.png, snapshot-2.png, etc:
private int _counter = 1;
private void clickButton_Click(object sender, EventArgs e)
{
webCamPictureBox.Image.Save(string.Format(“snapshot-{0}.png”, _counter++), System.Drawing.Imaging.ImageFormat.Png);
videoSource.SignalToStop();
}
Outra opção é perguntar o nome do arquivo que o usuário quer para a foto utilizando um SaveFileDialog.. Tem um exemplo na documentação do MSDN aqui:
https://msdn.microsoft.com/en-us/library/system.windows.forms.savefiledialog(v=vs.110).aspx
É isso aí.. Espero que eu tenha conseguido responder às suas dúvidas..
Abraço!
André Lima
Boa Noite!
Mais uma vez muito obrigado pela nova ajuda.
Usei a biblioteca DirectShow.NET e nao a Aforget.
Vou utilizar os códigos que vc disponibilizou para implementar mais um pouco a minha aplicação.
Obrigado. Gustavo Alvarenga.
Olá Gustavo,
Eu sugiro utilizar o Aforge que no final fica muito mais simples.. Qualquer dúvida, entre em contato.. Ah, e se você realmente decidir utilizar o DirectShow, me avise que eu tento adaptar as suas necessidades para essa biblioteca também..
Abraço!
André Lima
Boa noite! Mais uma vez muito obrigado pela ajuda. Fiz com a outra biblioteca (Aforget)e com todas as alterações que vc sugeriu, deu tudo certo. A única coisa que esta estranha e que quando eu usava a biblioteca DirectShow a imagem se alinhava de forma automática, agora preciso ficar movendo a câmera para que eu possa me enquadrar nela. A câmera esta reta com meu rosto, embora ela esta captando a imagem ao lado, como se estivesse torta. O que seria ?
Olá Gustavo!
Altere o SizeMode da sua PictureBox para “Zoom”.. Dessa forma a aplicação deve se comportar da maneira que você está querendo.. Me avise depois se funcionou!
Abraço!
André Lima
Muito obrigado pelo tutorial! Segui os passos e deu tudo certo.
Só uma dúvida.. Se não houver uma webcam conectada e eu clicar no botão de “chamar” a webcam, ele dá erro, falando que o índice não pode zero. Pensei em criar uma condicional, mas não sei qual seria a condição que eu colocaria. Tentei algumas coisas, mas não deu muito certo.
Eu utilizei a biblioteca AForge.
Opa.. Deixa para lá. Já consegui. Era só colocar um “try” e “catch”. Como não tinha pensado nisso antes? hehe
Olá Luan, obrigado pelo comentário!
Se você quiser evitar o try-catch (que eu recomendo, porque toda excessão lançada no sistema acaba deixando ele mais pesado), acredito que você pode verificar se a quantidade de videoSources é maior do que zero, e só continuar caso positivo.. Algo como:
if (videosources != null && videosources.Count > 0)
{
}
Tente aí e me conte depois e funcionou..
Abraço!
André Lima
Testei aqui e funcionou. Valeu! :)
Legal Luan! Fico feliz que tenha funcionado! Qualquer coisa é só falar..
Abraço!
André Lima
Boa tarde, parabéns excelente material, mas fiquei com uma dúvida…
ta funcionando direitinho conforme você colocou, mas gostaria de saber como faço, pois estou utilizando em um cadastro de funcionários, e gostaria de quando fosse consultar ele exibisse a foto, ou seja preciso apenas que guarde no banco o caminho de onde a foto foi salva…. e também gostaria de saber se tem como alterar o destino de onde será salvo essas fotos.
Olá Priscila, tudo bem? Obrigado pelo comentário!
Quanto à questão do lugar onde você vai salvar a foto, confira alguns comentários acima onde eu sugiro a utilização do SaveFileDialog para que o usuário escolha onde quer salvar a foto.. Além dessa opção, você pode também salvar em qualquer outro lugar do disco.. Para isso, basta incluir o caminho completo na hora de salvar a imagem (e não somente “snapshot.png”)..
Porém, eu recomendo que você não salve a imagem em disco, mas sim, salve a imagem no banco de dados.. Eu já escrevi um artigo no passado com algumas opções para salvar imagens no banco de dados.. Confira:
Salvando imagens no banco de dados utilizando C#
É isso aí, espero que tenha ajudado..
Abraço!
André Lima
Bom dia muito obrigada, vou dar uma olhada!!!
Bom dia André fiz como falou, mas surgiu um grande problema (pra mim pelo menos! rs), seguinte o meu é um cadastro de funcionário… até li o seu post referente a salvar no banco a imagem, mas não to conseguindo adaptar ele no meu projeto… pois a imagem não estará em uma tabela “sozinha” estará junto com várias outras colunas e eu preciso ligar o funcionário que estou gravando a foto que foi tirada.
Se puder me ajudar…..
Olá Priscila,
No seu caso, você pode criar uma nova coluna (do tipo binária) na tabela de funcionário para armazenar a foto.. E aí você precisa adaptar o seu código de salvar e carregar o funcionário considerando também a foto dele.. Como é que você está fazendo o armazenamento do funcionário? Com qual banco de dados você está trabalhando? Você está utilizando DataSets do ADO.NET, Entity Framework ou utilizando alguma outra tecnologia para salvar os dados no banco?
Abraço!
André Lima
então, sou bem novata nisso kkkkk
mas seguinte, estou usando com classe… exemplo:
tenho uma classe Fun:
//INCLUIR
public void inserir(String Nome, String Apelido, String CRMV, String CPF, String RG, String Sexo, DateTime Dt_Nasc, String Cargo, String Endereco, String Numero, String Complemento, String Bairro, String CEP, String Cidade, String Estado, String Pais, String Tel_Residencial, String Tel_celular, String Senha, String Resp_Alteracao)
{
try
{
//MessageBox.Show(“insert into funcionario(Nome, Apelido, CRMV, CPF, RG, Sexo, Dt_Nasc, Cargo, Endereco, Numero, Complemento, Bairro, CEP, Cidade, Estado, Pais, Tel_Residencial, Tel_Celular, Senha, Resp_Alteracao)values(‘” + Nome + “‘, ‘” + Apelido + “‘, ‘” + CRMV + “‘ , ‘” + CPF + “‘ , ‘” + RG + “‘, ‘” + Sexo + “‘, ‘” + Dt_Nasc + “‘, ‘” + Cargo + “‘, ‘” + Endereco + “‘, ‘” + Numero + “‘, ‘” + Bairro + “‘,'” + Complemento + “‘, ‘” + CEP + “‘, ‘” + Cidade + “‘, ‘” + Estado + “‘, ‘” + Pais + “‘, ‘” + Tel_Residencial + “‘, ‘” + Tel_celular + “‘, ‘” + Senha + “‘, ‘” + Resp_Alteracao +”‘);”);
SqlCommand meucomando = new SqlCommand(“insert into funcionario(Nome, Apelido, CRMV, CPF, RG, Sexo, Dt_Nasc, Cargo, Endereco, Numero, Complemento, Bairro, CEP, Cidade, Estado, Pais, Tel_Residencial, Tel_Celular, Senha, Resp_Alteracao)values(‘” + Nome + “‘, ‘” + Apelido + “‘, ‘” + CRMV + “‘ , ‘” + CPF + “‘ , ‘” + RG + “‘, ‘” + Sexo + “‘, ‘” + Dt_Nasc + “‘, ‘” + Cargo + “‘, ‘” + Endereco + “‘, ‘” + Numero + “‘, ‘” + Bairro + “‘,'” + Complemento + “‘, ‘” + CEP + “‘, ‘” + Cidade + “‘, ‘” + Estado + “‘, ‘” + Pais + “‘, ‘” + Tel_Residencial + “‘, ‘” + Tel_celular + “‘, ‘” + Senha + “‘, ‘” + Resp_Alteracao + “‘);”, TB.minhaconexao);
TB.minhaconexao.Open();
meucomando.ExecuteNonQuery();
MessageBox.Show(“Operação realizada com sucesso!”, “Sucesso”, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception Ex)
{
MessageBox.Show(“Não foi possível realizar a operação! ” + Ex.Message);
}
finally
{
TB.minhaconexao.Close();
}
}
e no meu form eu estâncio essa classe e chamo o método inserir:
private void btnsalvar_Click(object sender, EventArgs e)
{
String CripSenha = AcertaSenha(txtsenha.Text);
//INCLUIR
if (OP == “Incluir”)
{
if (this.valida() == true)
{
String dataFormatada = TB.formataData(txtnasc.Text);
ClassFunc.inserir(txtnome.Text, txtapelido.Text, txtcrmv.Text, txtcpf.Text, txtrg.Text, cmbsexo.Text, DateTime.Parse(txtnasc.Text), cmbcargo.Text, txtendereco.Text, txtnumero.Text, txtbairro.Text, txtcomplemento.Text, txtcep.Text, txtcidade.Text, txtestado.Text, txtpais.Text, txttelresidencial.Text, txttelcelular.Text, AcertaSenha(txtsenha.Text), txtrespalteracao.Text);
this.capturarfoto();
this.Limpar();
this.reseta();
tabControlFuncionario.SelectedTab = tabconConsulta;
}
else
{
MessageBox.Show(“Existe algum campo em branco!”,”Verificar”,MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
no banco está:
CREATE TABLE FUNCIONARIO (
COD_FUN INT IDENTITY (1,1) NOT NULL PRIMARY KEY,
NOME VARCHAR(40) NOT NULL,
APELIDO VARCHAR(10) NOT NULL,
CRMV VARCHAR(10) NULL,
CPF VARCHAR(14) NOT NULL,
RG VARCHAR(12) NULL,
SEXO VARCHAR(9) NOT NULL,
DT_NASC DATE NOT NULL,
CARGO VARCHAR(14) NOT NULL,
ENDERECO VARCHAR(40) NOT NULL,
NUMERO VARCHAR(5) NOT NULL,
COMPLEMENTO VARCHAR(15) NULL,
BAIRRO VARCHAR(25) NOT NULL,
CEP VARCHAR(9) NOT NULL,
CIDADE VARCHAR(20) NULL,
ESTADO VARCHAR(2) NULL,
PAIS VARCHAR(10) NULL,
TEL_RESIDENCIAL VARCHAR(13) NULL,
TEL_CELULAR VARCHAR(14) NULL,
SENHA VARCHAR(200) NOT NULL,
RESP_ALTERACAO VARCHAR(40) NULL,
FOTO IMAGE
)
Olá Priscila, desculpe a demora em responder..
Você está no caminho certo, mas, gostaria de sugerir algumas melhorias.. Primeiramente, ao invés de concatenar os valores na sua sentença, utilize a funcionalidade de parâmetros do ADO.NET.. Dessa forma, você não precisa ficar se preocupando com as aspas para valores string, além de proteger o seu aplicativo contra SQL Injection.. Veja mais sobre esse assunto aqui:
http://www.csharp-station.com/Tutorial/AdoDotNet/lesson06
Após ter alterado o seu código com a utilização de parâmetros, para suportar a inserção da imagem, a única diferença é que você terá que extender a sua sentença considerando o campo “FOTO” e você terá mais um parâmetro correspondente à foto (aquele meu artigo que eu passei o link sobre salvar imagens no banco de dados tem um exemplo muito fácil disso – veja o método “SalvarFotoAdoNet”)..
É isso aí, espero que tenha ajudado.. Se ficar com mais alguma dúvida, é só entrar em contato!
Abraço,
André Lima
Bom dia,
Brigadão André vou dar uma olhada sim!!!
Oi André ainda não consegui solucionar meu problema…
mas uma dúvida rápida, com este código que vc passou do Aforge, como faço para colocar em uma variável o caminho onde a imagem foi salva ?
Olá novamente Priscila,
Se você utilizar o exemplo do jeito que está escrito, ele sempre salvará a imagem no mesmo diretório da aplicação com o nome “snapshot.png”.. Para dar a possibilidade do usuário escolher o local onde a imagem será salva utilizando o SaveFileDialog, o código ficaria mais ou menos assim:
using (SaveFileDialog dialog = new SaveFileDialog())
{
dialog.Filter = “PNG (*.png)|*.png”;
if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
var caminho = dialog.FileName;
webCamPictureBox.Image.Save(caminho, System.Drawing.Imaging.ImageFormat.Png);
}
}
Se estiver com dificuldades, por favor, detalhe exatamente os passos que você seguiu e em que parte você está com dúvida.. Se preferir, entre em contato por e-mail (meu e-mail está disponível na minha página “Sobre“)..
Abraço!
André Lima
Ola André, tudo bem com vc?
Amigo sou novato em .net minha área é infraestrutura, mas estou a alguns meses estudando muito c#. Fiz um uma aplicação a qual capturarei a foto para cadastro. Utilizei da forma que você vez. Mas estou encontrando um erro aqui que não consigo solucionar.
public partial class frmWebCam : Form
{
AForge.Video.DirectShow.VideoCaptureDevice videoSource;
public frmWebCam()
{
AForge.Video.DirectShow.FilterInfoCollection videosources = new AForge.Video.DirectShow.FilterInfoCollection(AForge.Video.DirectShow.FilterCategory.VideoInputDevice);
if (videosources != null)
{
videoSource = new AForge.Video.DirectShow.VideoCaptureDevice(videosources[0].MonikerString);
videoSource.NewFrame += (s, e) => webCamPictureBox.Image = (Bitmap) e.Frame.Clone();
videoSource.Start();
}
}
private void button1_Click(object sender, EventArgs e)
{
webCamPictureBox.Image.Save(“snapshot.png”, System.Drawing.Imaging.ImageFormat.Png);
}
}
neste trecho em específico
videoSource.NewFrame += (s, e) => webCamPictureBox.Image = (Bitmap) e.Frame.Clone();
O visual studio me da a mansagem NullReferenceException was unhandled by user code.
An exception of type ‘System.NullReferenceException’ occurred in ERP.exe but was not handled in user code.
Se puder me ajudar ficaria muito agradecido.
Forte Abraço.
Marcos Perez
Olá Marcos,
Pela mensagem de erro, imagino que “e”, “e.Frame” ou “e.Frame.Clone()” esteja retornando nulo.. Para deixar esse trecho de código mais robusto e menos propício a excessões, você pode alterá-lo para algo como:
videoSource.NewFrame += (s, e) =>
{
if (e != null && e.Frame != null)
{
var bmp = e.Frame.Clone() as Bitmap;
if (bmp != null)
webCamPictureBox.Image = bmp;
}
};
Abraço!
André Lima
[…] do possível, utilizar bibliotecas já prontas que dão conta do recado. Por exemplo, você quer tirar fotos com a webcam no seu aplicativo? Utilize uma biblioteca pronta que implementa essa funcionalidade. O mesmo vale para leitura de […]
Cara, parabéns pelo tópico!!!
Olá Tony, obrigado pelo comentário! Fico feliz que você tenha gostado! Ah, e obrigado por ter assinado a minha newsletter também.. :)
Abraço!
André Lima
[…] vou utilizar a aplicação que construímos no artigo de três semanas atrás, onde aprendemos como tirar fotos com a webcam em C#. Esse exemplo cabe como uma luva nessa situação, uma vez que ele contém não somente um […]
Muito bom seu artigo, mas como que seria para tirar varias fotos? Tentei bitmap.Save(“snapshot*.png”, System.Drawing.Imaging.ImageFormat.Png); mas nao deu certo
Olá Fa, obrigado pelo comentário!
Dê uma olhada nos comentários anteriores.. Eu sugeri duas maneiras de implementar essa funcionalidade.. Primeiro, no meu comentário de 09/07/2015, em resposta para a pergunta do Gustavo Alvarenga, eu mostrei uma opção, que é salvar os arquivos automaticamente como snapshot-1, snapshot-2, etc, dependendo de quantas fotos você tirar.. Aqui vai o link para este comentário: http://www.andrealveslima.com.br/blog/index.php/2014/11/07/tirando-fotos-com-a-webcam-em-c/#comment-35647
Já a segunda opção é mostrar um SaveFileDialog.. Dessa forma o usuário poderá escolher o local e nome do arquivo que ele quer utilizar para cada foto.. Essa opção eu mostrei no comentário de 04/08/2015, em resposta para a pergunta da Priscila.. Aqui vai o link para o comentário em questão: http://www.andrealveslima.com.br/blog/index.php/2014/11/07/tirando-fotos-com-a-webcam-em-c/#comment-35793
Espero que ajude!
Abraço!
André Lima
Muito bom cara…Parabéns…
Eu só estou com uma dificuldade…eu gostaria que a camera nao fosse ligada quando inicializar o formulario, e sim que tenha um bota para “Ligar a camera”…poderia me ajudar???
Agradeço desde já.
Olá Weslei!
Primeiramente, obrigado pelo comentário! Para fazer isso que você está querendo, basta seguir estas etapas:
1 – Remova a chamada de videoSource.Start(); do construtor do formulário
2 – Adicione um botão no formulário (que vai servir para a funcionalidade de on/off da camera) e adicione o seguinte código no seu Click:
Pronto!
Abraço!
André Lima
Muio bom cara..Muito Obrigado…Funcionou perfeitamente…Parabens
Magina Weslei! Fico feliz que tenha funcionado!
Qualquer coisa entre em contato novamente..
Abraço!
André Lima
Olá André,
Bom dia!
Existe possibilidade da gente usar a webcam com algumas API’s do próprio windows ?
Olá Emanuel, obrigado pelo comentário!
Como assim usar a webcam com as APIs do próprio Windows? Você quer dizer com o WIA (Windows Image Acquisition)? Se sim, eu nunca fiz, mas, aparetemente é possível:
WebCam Fast Image Capture Service using WIA
Catch a Snapshot via your webcam using C#
Take a picture automatically using a webcam in C# using WIA
Se você estiver falando de outra coisa, por favor, dê maiores detalhes..
Abraço!
André Lima
André,
Como faz referencia as DLL no projeto? Imagino que seja bem simples, dei uma olhada no Google, mas ainda não consegui. Eu sou novato em desenvolvimento .NET. Poderia me dar esta dica?
Obrigado
Olá Pierre,
É só ir no Solution Explorer, clicar com o botão direito em “References”, escolher “Add Reference”.. Na tela que se abre, você precisa encontrar o local onde as dlls estão armazenadas e adicionar a referência..
Na documentação do MSDN tem um tópico só sobre esse assunto:
Como adicionar ou remover referências usando a caixa de diálogo Adicionar Referência
Abraço!
André Lima
Parabéns pelo blog, André Lima! Estou fazendo o meu projeto da faculdade que é o controle de entrada e saída de veículos. Montarei uma maquete com arduino e a câmera apresentada no blog. Preciso que a câmera tire a foto e armazene no banco de dados apenas o dia/mês/ano e horário, as fotos irão para o diretório do computador. A minha maior dificuldade é integrar a câmera com a aplicação. Teria como me dar uma ajuda? Toda ajuda é bem vinda. Agradeço desde já.
Olá Felipe,
Não tenho ideia se as bibliotecas apresentadas nesse artigo funcionam com o Arduino.. E eu infelizmente não tenho nenhuma experiência com o Arduino ainda..
Você tentou construir as aplicações de exemplo? Você já começou o projeto? Dê maiores detalhes do que você já tem hoje.. Talvez aí eu consiga te ajudar melhor..
Abraço!
André Lima
Olá, implementei seu código no meu projeto. Utilizei a biblioteca AForge.NET. Ao acionar o botão para salvar a foto, o visual studio para e reinicia. Não consegui descobrir a causa do problema (lembrando que estou usando a webcam interna).
Desde já, Grato!
Olá Lucas!
Estranho.. Nunca tive problema com a biblioteca AForge.. Já utilizei em vários computadores, com webcam externa ou interna..
Você tem a possibilidade de testar o exemplo em outro computador? Uma coisa que você poderia tentar é executar a aplicação sem estar em modo debug (Debug -> Start without debugging) para ver se você não tem uma mensagem de erro mais detalhada.. Além disso, dê uma olhada também no log de eventos do Windows para ver se você não encontra maiores detalhes sobre o erro..
Abraço!
André Lima
André, parabéns pelo post!
Me ajudou bastante. Apliquei a dll do Aforge no meu projeto e superou as expectativas.
Só uma dúvida, ao invés de colocar no construtor do FORM, eu tentei criar uma função para seja chamada ao click de um botão tipo “ativa webcam”, pois não quero que ela seja ativada ao abrir o form…
porém quando coloco essa parte do código abaixo fora do construtor do FORM, por exemplo na função on click de um botão, ele dá um erro dizendo que não encontrou o elemento “e”, que está em “+= (s, e)”. Não consegui entender o pq. No mais, funciona perfeitamente.
AForge.Video.DirectShow.FilterInfoCollection videosources = new AForge.Video.DirectShow.FilterInfoCollection(AForge.Video.DirectShow.FilterCategory.VideoInputDevice);
if (videosources != null)
{
videoSource = new AForge.Video.DirectShow.VideoCaptureDevice(videosources[0].MonikerString);
videoSource.NewFrame += (s, e) => pictureBoxWebCam.Image = (Bitmap)e.Frame.Clone();
videoSource.VideoResolution = videoSource.VideoCapabilities[4];
videoSource.Start();
}
Olá Thiago, obrigado pelo comentário!
Desculpe a demora em responder.. É que meu segundo filho nasceu no final de semana retrasado e eu acabei tirando a semana passada off..
Quanto à sua dúvida, o que pode estar acontecendo é que, como você está utilizando esse código dentro de um outro event handler (evento click de um botão), provavelmente você já tem uma outra variável “e” declarada (na assinatura do método SeuBotao_Click).. O que você pode fazer nesse caso é dar outro nome para o segundo “s” e “e”.. Por exemplo, “s2” e “e2”:
Tenta aí e me avisa depois se funcionou..
Grande abraço!
André Lima
André por favor tem como você me ajudar!! fiz do jeito que você ensinou direitinho , mas queria salvar a foto junto com os dados do cliente, o unico problema é que eu nao uso o server ,so uso o sqlDeveleper(oracle) e nao tenho ideia de como vou fazer isso.
e quando eu fosse consultar dos dados do cliente a foto vai carregar junto!!por favor preciso muito da sua ajuda
Olá Hellen!
Uns tempos atrás eu expandi esse artigo mostrando como salvar a imagem no banco de dados.. No artigo eu utilizo o SQL Server, mas, para salvar no Oracle é exatamente a mesma coisa.. Só que ao invés de utilizar o provider do SQL Server você tem que utilizar o provider do Oracle (mas os comandos são os mesmos).. Dá uma olhada:
Salvando imagens no banco de dados utilizando C#
Se você não conseguir, me avisa qual é exatamente a dificuldade que você está tendo que eu te ajudo de outra forma..
Abraço!
André Lima
Olá André , não conseguir salvar ainda!
no lugar de criar uma tabela só para armazenar as fotos eu coloquei junto com os dados do cliente !
olha:CREATE TABLE T_Cliente — cria uma tabela Cliente
(
cod_Cliente number (5),
NOME VARCHAR2 (100) NOT NULL,
NOMERESP VARCHAR2 (50) NULL,
CPF VARCHAR2 (16) NULL,
RG VARCHAR2 (20) NOT NULL,
CPF_RESP VARCHAR2 (16) NULL,
RG_RESP VARCHAR2 (20) NULL,
BAIRRO VARCHAR2(50) NOT NULL,
CIDADE VARCHAR2 (100) NOT NULL,
UF CHAR (2) NOT NULL,
NR VARCHAR2 (5) NOT NULL,
DTNASC VARCHAR2(10) NOT NULL,
TELEFONE VARCHAR2 (20) NOT NULL,
CELULAR VARCHAR2 (20) NOT NULL,
SEXO VARCHAR2 (10 )NOT NULL,
CEP VARCHAR2 (20) NOT NULL,
ENDERECO VARCHAR2 (100)NOT NULL,
FOTO VARCHAR2 (600) NULL,
ATIVO NUMBER (1),
constraint PK_cod_Cliente primary key (cod_Cliente)
);
COMMIT;
Assim eu poderia Salvar os dados do cliente com a foto!
e não to conseguindo conectar com o dataset do c#!
meu Professor de android disse que era para usar o blooded ! tentei converter o código para c# e pesquisei bastante sobre ele ,so que não conseguir
Abraço!
Olá Hellen!
O campo para a imagem deve ser do tipo BLOB.. Uma vez o campo sendo desse tipo, você pode seguir a mesma ideia apresentada neste artigo para salvar a imagem.. Tem também um outro artigo no CodeProject (em inglês) que mostra como salvar imagens nos campos BLOB do Oracle com C#:
Insert /retrieve an image into/ from a blob field in Oracle database using C#.Net
Abraço!
André Lima
Olá André !
Então seguir passo a passo do link que você me passou , mas ele não ta salvando o caminho da imagem ainda!
tipo eu tiro a foto e salvo com os dados quando vou pesquisar os dados e a foto não aparece a foto nem da para consultar o caminho (to usando um DatagridView para consultar os dados do cliente junto com a foto mais não aparece.
Olá Hellen!
Você poderia postar como está o seu código? Se você conseguir, seria ainda melhor se você conseguisse compactar o seu projeto, subir no Dropbox ou OneDrive e mandar o link para baixá-lo..
Abraço!
André Lima
public partial class FormCliente : Form
{
AForge.Video.DirectShow.VideoCaptureDevice videoSource;
public FormCliente()
{
InitializeComponent();
AForge.Video.DirectShow.FilterInfoCollection videosources = new AForge.Video.DirectShow.FilterInfoCollection(AForge.Video.DirectShow.FilterCategory.VideoInputDevice);
if (videosources != null)
{
videoSource = new AForge.Video.DirectShow.VideoCaptureDevice(videosources[0].MonikerString);
videoSource.NewFrame += (s, e) => webCamPictureBox.Image = (Bitmap)e.Frame.Clone();
videoSource.Start();
}
}
clnFuncoesGerais.Operacao ObjOperacao;
public clnFuncoesGerais.Operacao EnumProperty
{
get { return ObjOperacao; }
set { ObjOperacao = value; }
}
private void FormCliente_Load(object sender, EventArgs e)
{
maskCPFresp.Enabled = false;
txtNomeResp.Enabled = false;
txtEndereco.Enabled = false;
comboUF.Enabled = false;
txtBairro.Enabled = false;
txtCidade.Enabled = false;
txtCodigo.Enabled = false;
if (txtCodigo.Text != “”)
{
clnAgenda objclnAgenda = new clnAgenda();
OracleDataReader objDRDados;
objDRDados = objclnAgenda.ListarUsuario(txtCodigo.Text);
if (objDRDados.Read())
{
txtNomeCompleto.Text = objDRDados[“NOME”].ToString();
txtNomeResp.Text = objDRDados[“NOMERESP”].ToString();
maskCPF.Text = objDRDados[“CPF”].ToString();
maskRG.Text = objDRDados[“RG”].ToString();
maskCPFresp.Text = objDRDados[“CPF_RESP”].ToString();
maskRGresp.Text = objDRDados[“RG_RESP”].ToString();
txtBairro.Text = objDRDados[“BAIRRO”].ToString();
txtCidade.Text = objDRDados[“CIDADE”].ToString();
comboUF.Text = objDRDados[“UF”].ToString();
txtNumero.Text = objDRDados[“NR”].ToString();
maskDataNasc.Text = objDRDados[“DTNASC”].ToString();
maskTelefone.Text = objDRDados[“TELEFONE”].ToString();
maskCelular.Text = objDRDados[“CELULAR”].ToString();
comboSexo.Text = objDRDados[“SEXO”].ToString();
maskCEP.Text = objDRDados[“CEP”].ToString();
txtEndereco.Text = objDRDados[“ENDERECO”].ToString();
webCamPictureBox.Text = objDRDados[“FOTO”].ToString();
}
}
txtNomeCompleto.Focus();
}
private void btnSalvar_Click_1(object sender, EventArgs e)
{
if ((txtNomeCompleto.Text == “”) || (maskTelefone.Text == “”) || (maskCPF.Text == “”) || (maskCEP.Text == “”) || (comboSexo.Text == “”))
{
MessageBox.Show(“Os campos com * são de preenchimento obrigatorios”);
txtNomeCompleto.Focus();
}
else
{
clnAgenda Agenda = new clnAgenda();
if (txtCodigo.Text != “”)
{
Agenda.cod_Cliente = Convert.ToInt32(txtCodigo.Text);
}
Agenda.NOME = txtNomeCompleto.Text;
Agenda.NOMERESP = txtNomeResp.Text;
Agenda.CPF = maskCPF.Text.Replace(“-“, “”);
Agenda.RG = maskRG.Text.Replace(“-“, “”);
Agenda.CPF_RESP = maskCPFresp.Text.Replace(“-“, “”);
Agenda.RG_RESP = maskRGresp.Text.Replace(“-“, “”);
Agenda.BAIRRO = txtBairro.Text;
Agenda.CIDADE = txtCidade.Text;
Agenda.UF = comboUF.Text;
Agenda.NR = txtNumero.Text;
Agenda.DTNASC = maskDataNasc.Text;
Agenda.TELEFONE = maskTelefone.Text.Replace(“()”, “-“);
Agenda.CELULAR = maskCelular.Text;
Agenda.SEXO = comboSexo.Text;
Agenda.CEP = maskCEP.Text.Replace(“-“, “”);
Agenda.ENDERECO = txtEndereco.Text;
Agenda.FOTO = webCamPictureBox.Text;
if (ObjOperacao == clnFuncoesGerais.Operacao.Inclusao)
{
Agenda.Gravar();
MessageBox.Show(“Matricula gravada com sucesso!!”, “Item Novo ” + txtNomeCompleto.Text,
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else if (ObjOperacao == clnFuncoesGerais.Operacao.Alteracao)
{
Agenda.Alterar(Convert.ToInt32(txtCodigo.Text));
MessageBox.Show(“Registro nº” + txtCodigo.Text + “Alterado com sucesso”,
“Alteração”, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
Close();
}
}
private void webCamPictureBox_Click(object sender, EventArgs e)
{ videoSource.Start();
}
private void clickButton_Click(object sender, EventArgs e)
{
webCamPictureBox.Image.Save(string.Format(“snapshot-{0}.png”, _counter++), System.Drawing.Imaging.ImageFormat.Png);
videoSource.SignalToStop();
salvar(Application.StartupPath + “\\snapshot-{0}.png”);
videoSource.NewFrame += (s2, e2) => webCamPictureBox.Image = (Bitmap)e2.Frame.Clone();
//Teste 23-06-16 –
var stream = new System.IO.MemoryStream();
webCamPictureBox.Image.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
stream.Seek(0, System.IO.SeekOrigin.Begin);
byte[] bArray = new byte[stream.Length];
stream.Read(bArray, 0, System.Convert.ToInt32(stream.Length));
//OracleBlob fotoBanco = bArray;
}
private int _counter = 1;
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
if (videoSource != null && videoSource.IsRunning)
{
videoSource.SignalToStop();
videoSource = null;
}
}
private PictureBox salvar(string caminho)
{
this.webCamPictureBox.Image.Save(caminho);
return webCamPictureBox;
}
}
}
Olá André aqui está , não conseguir compactar o meu projeto, esse codigo é do form do cliente
Essa parte aqui meus professores estava mexendo ,mas depois parou:
” salvar(Application.StartupPath + “\\snapshot-{0}.png”);
videoSource.NewFrame += (s2, e2) => webCamPictureBox.Image = (Bitmap)e2.Frame.Clone();
//Teste 23-06-16 –
var stream = new System.IO.MemoryStream();
webCamPictureBox.Image.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
stream.Seek(0, System.IO.SeekOrigin.Begin);
byte[] bArray = new byte[stream.Length];
stream.Read(bArray, 0, System.Convert.ToInt32(stream.Length)); “
Olá Hellen!
Está um pouco difícil conseguir entender o que você está fazendo.. Mas, pelo que percebi, um dos problemas pode ser porque você está salvando webCamPictureBox.Text no campo FOTO.. Na verdade você tem é que salvar o caminho da imagem.. E o caminho da imagem não estará armazenado na propriedade Text do PictureBox.. O que você poderia fazer é armazenar o caminho em algum outro lugar (por exemplo, em uma variável no nível do formulário ou na propriedade Tag do PictureBox) e aí utilizar esse conteúdo na hora de armazenar o campo FOTO..
Depois, na hora de carregar, você só está setando a propriedade Text do PictureBox.. Isso também está errado.. Para carregar a imagem você tem que preencher a propriedade Image com uma nova instância da classe Bitmap passando o caminho da imagem:
webCamPictureBox.Image = new Bitmap(caminhoDaImagem);
Abraço!
André Lima
Olá André conseguir compactar meu projeto
Aqui o link:
https://www.dropbox.com/s/1pkmdpwtp4vtck6/TCC-ITB-Escola.rar?dl=0
abraços
Olá Hellen!
Infelizmente o link não está funcionando.. Está retornando um “Link not found”:
Será que tem como colocar o projeto novamente em um outro link?
Abraço!
André Lima
André, com estas libs eu consigo gravar videos com audio?
ótimo post.
Olá André!
Com a AForge não é possível capturar o áudio, somente a imagem.. Já o DirectShow.Net aparentemente suporta a captura de ambos, mas, eu nunca testei.. Tem um tutorial aqui que você pode tentar e depois fala pra gente se funcionou:
Capturing webcam using DirectShow.NET library
Pelo que pesquisei, outra biblioteca que possibilita a captura de vídeo e áudio ao mesmo tempo é o Microsoft Expression Encoder.. Tem um tutorial aqui:
How to use a web cam in C# with .NET Framework 4.0 and Microsoft Expression Encoder 4
Abraço!
André Lima
[…] 5) Tirando fotos com a WebCam em C# […]
Olá, André
Graças a sua explicação consegui executar minha aplicação. Mas, depois de criar um instalador para meu projeto, quando instalo em um PC que não tem a webcam a aplicação, obviamente, cria uma exceção sem tratamento. Eu gostaria de saber como faço, por exemplo, para que antes de a webcam seja iniciada, a aplicação verifique se a mesma tem a webcam no PC. E caso não tenha, ele não execute.
Olá Lucas!
Precisaria ver direitinho em qual linha a exceção está sendo disparada, mas, eu acredito que seja na criação do VideoCaptureDevice.. Nessa linha, se o computador não tiver webcam ele vai tentar acessar videosources no índice zero, que não existirá e provavelmente lançará uma exceção..
A primeira tentativa que eu faria seria melhorar a condição “if” para checar, além do videosources != null, verificar também se a quantidade de videosources é maior que um.. Algo como:
Agora, se isso não resolver o problema, eu precisaria de uma stack trace mais detalhada para saber em qual linha a exception está sendo disparada..
Abraço!
André Lima
André, melhorei minha condição e deu super certo!
Muito Obrigado!
Maravilha, Lucas! Fico feliz que tenha dado certo.. Qualquer coisa é só entrar em contato..
Abraço!
André Lima
Olá testei com a biblioteca AForge.NET mas não funcionou, não deu erro mas não aparece a imagem, estou usando visual studio 2015
Olá, resolvi o problema do post anterior, minha webCam esta na posição 1 e não 0 da coleção videosources[1]
Olá novamente Alexandre!
Que estranho hein.. Nunca vi uma situação em que a webcam não estivesse no índice zero.. Vai entender.. Pelo menos você conseguiu detectar a origem do problema.. Valeu por voltar aqui e compartilhar a solução! Qualquer coisa é só entrar em contato novamente..
Abraço!
André Lima
Perfeito! Funcionou show!!! Boa!
Pra complicar um pouco eu queria colocar um botão na tela de captura e pegasse a imagem da table e jogasse em outra table de outro form…é possível?
Tipo a pessoa fica lá tirando um monte de fotos, daí fica satisfeita com uma e clica nesse botão, até aí foi tudo salvo na table Foto, esse botão pega essa foto e manda pra outra table, que não é a Foto, pra guardar a imagem, daí a pessoa fecha o form de captura e o todas as imagens são apagadas, da table Foto, pra não ficar acumulando… Não pode fazer uma chave secundária pq daí não pode mais truncar a table Foto… empaquei aqui…
Olá Fernando, muito obrigado pelo comentário!
Não entendi muito bem o que você está querendo fazer, será que você poderia explicar melhor? De preferência com uns screenshots da sua aplicação para ficar mais fácil de entender..
Se você quer tirar múltiplas fotos na mesma janela, você não precisa salvar no banco.. O que você poderia fazer é guardá-las em memória (em um array de Images, por exemplo) e depois o usuário escolhe a imagem que quer retornar para o outro formulário.. Essa imagem você consegue passar para o outro formulário criando uma propriedade pública nele (“ImagemSelecionada”, por exemplo)..
Enfim, dê mais detalhes do seu projeto para eu conseguir te ajudar melhor.. Se preferir, pode mandar por e-mail: contato [arroba] andrealveslima [ponto] com [ponto] br
Abraço!
André Lima
AH, trabalhei nisso até hoje, consegui.
Eu pensei no seguinte: se o usuário fica lá tirando fotos, tudo bem, e vai gravando no banco foto, que está num form separado com as funcionalidades da camera, daí ele seleciona a foto que achar melhor pelo list, e clica no botao selecionar, esse botao salva a imagem no banco de cadastro, fecha o form e esvazia o banco foto. Assim o user vai ser devolvido pro form de cadastro com a foto dele lá no lugar. Deu certinho, inclusive passa pro datagrid e exibe a imagem de cada cadastrado, ainda não consegui ajustar o tamanho da imagem no grid…vc sabe fazer isso?
Vou terminar e organizar tudo de novo pq zoniei todo o form fazendo testes…kkkk
Ah, tem como dar um flip na imagem da camera pelo Aforge, aí ficava 110%? a minha camera pelo menos mostrou uma imagem espelhada….
Gostei daqui viu, vou tentar participar mais…fico preocupado em incomodar pq ainda tenho duvidas muito básicas…
Olá Fernando, que bom que você conseguiu resolver! Mas, deixa eu te perguntar uma coisa: a sua aplicação é multi-usuário (ela pode ser executada em computadores diferentes ao mesmo tempo apontando para o mesmo banco de dados)? Caso positivo, você pode ter problemas de conflito caso mais de um usuário esteja tirando fotos ao mesmo tempo..
Quanto à sua pergunta da imagem espelhada, isso é um saco mesmo.. Algumas câmeras acabam espelhando a imagem.. Você pode tentar fazer um flip na imagem utilizando o método RotateFlip da classe Bitmap, passando a opção RotateFlipType.RotateNoneFlipX.. Dá uma olhada nestes links e veja se você entende a ideia:
Image.RotateFlip Method (RotateFlipType)
Flip Image(Mirror) in a PictureBox Control
E fique à vontade para postar outras dúvidas aqui ou, se preferir, pode me mandar por e-mail também: contato [arroba] andrealveslima [ponto] com [ponto] br
Abraço!
André Lima
André, tudo certo?!
Muito obrigado pela dica sobre as bibliotecas. Ajudou bastante no que eu queria fazer (acabei optando por usar a própria AForge, instalei pelo Nuget).
Só queria deixar uma pequena correção no seu código, não sei se alguém comentou aí pra cima..
No trecho:
videoSource.NewFrame += (s, e) => webCamPictureBox.Image = (Bitmap)e.Frame.Clone();
Nós devemos dar um Dispose na imagem da PictureBox antes de clonar o novo frame, se não o programa aloca muita memória (700 MB na minha máquina) antes de o GC coletar..
O novo trecho seria:
videoSource.NewFrame += (s, e) =>
{
if(webCamPictureBox.Image != null) {
webCamPictureBox.Image.Dispose();
}
webCamPictureBox.Image = (Bitmap)e.Frame.Clone();
}
Mais uma vez, obrigado pelo tutorial. Abraço!
Olá Luiz, muito obrigado pelo comentário!
Excelente observação.. Não tinha reparado nisso quando escrevi o artigo.. Já ajustei aqui o código de exemplo adicionando a chamada ao Dispose..
Um grande abraço!
André Lima
[…] e intuitiva, muito simples de utilizar. Uns tempos atrás eu escrevi um artigo onde eu mostrei como tirar fotos com a webcam no C#, onde eu utilizei tanto a biblioteca AForge quanto a biblioteca DirectShow.NET. Como esse é um dos […]
ola, muito bom o artigo mas estou tentando fazer captura em webpage webforms..
E nao acho nenhum exemplo.. e nao sei como transportar o codigo para webforms..
nem na produtora do aforge.. agradeco se existir um codigo fonte simples so para captura de imagem em windows 10 vs2017..
Olá Jorge, muito obrigado pelo comentário!
Infelizmente essa eu vou ficar te devendo.. Não tenho praticamente nenhuma experiência com desenvolvimento web, portanto, não saberia te indicar um componente nesse caso..
Mas, eu já ouvi falar que o próprio HTML5 tem suporte à captura de webcam.. Você já chegou a dar uma pesquisada nisso? Por exemplo, pesquisando rapidamente aqui, eu encontrei este artigo:
Capturing Audio & Video in HTML5
Abraço!
André Lima
Olá, André, blz?
Olha que coisa incrível! Meu cunhado me solicitou a possibilidade de desenvolver um sistema de Cartão de ponto que tirasse uma foto da pessoa quando ela marcasse o ponto (num sistema Windows Form, mesmo!). Falei pra ele que eu nunca tinha feito, mas, tinha certeza que era possível. Só pesquisar um pouco.
Não é que na primeira pesquisa que eu realizo caio num artigo seu? E olha que é um artigo de 2014!!!! E eu precisando disso em 2017!!! Que maravilha!!!
Cara, cada vez mais me surpreendo com sua capacidade. Parabéns, cara!
Todos os seus artigos são de excelente qualidade e de uma clareza impressionantes!
Seu artigo sobre SQLite me ajudou imensamente, apesar de só utilizá-lo, por enquanto, em aplicações exemplos e pequenos projetos.
Minha intenção é conseguir fazer alguma coisa com ele em Android, mas, ainda estou longe desta etapa.
Grato novamente pelo artigo e, com certeza, vou utilizá-lo no meu projeto!!!
Abraços e parabéns novamente!
Fala André!
Que massa hein! Muito legal que mesmo os artigos mais antigos continuam ajudando novas pessoas todos os dias.. Valeu demais pelos elogios! :)
Precisando de alguma ajuda é só entrar em contato..
Abraço!
André Lima
Ola, não está mais disponivel o link para baixar a biblioteca da DirectShow.NET… clickei e deu erro… https://sourceforge.net/projects/directshownet/files/DirectShowNET/v2.1/
Olá Denise!
Eu acabei de testar aqui e a página de download da biblioteca DirectShow.NET está funcionando.. Será que não era alguma indisponibilidade temporária?
Caso você não consiga baixá-la manualmente, você pode tentar adicionar a referência pelo NuGet:
https://www.nuget.org/packages/DirectShowLib/
Abraço!
André Lima