Voce tem uma empresa, voce desenvolve programas Open Source no meu segmento.
Porque deveria contratar um concorrente?
Naquele momento, percebi que minhas intensões não estavam sendo claras. E resolvi publicar este artigo.
Projeto Open Source nunca concorre com aplicações comerciais. Eu nunca ví, em meus 24 anos de carreira, uma empresa que faliu por conta de um software open source.
A única coisa que ví, foi a Microsoft, que depois de muito sofrimento, aderiu ao mundo open source. Hoje está ganhando dinheiro com Linux.
Então, se voce souber de alguma empresa que faliu por conta de um projeto open source, é bom falar agora, ou cale-se para sempre.
Software Open Source, são em sua essencia ferramentas de fomento e desenvolvimento.
Quando desenvolvemos um projeto Open source estável e seguro, este, cria um leque de possibilidades e serviços que qualquer empresa pode agregar.
De fato, projetos open source criam oportunidades, não as tira.
O Linux é o maior CASE do mundo open source, mas não é o unico.
Existem vários, como:
APACHE
Blender
Docker
GIT
KUBERNETES
R
SUGARCRM
Entre tantos outros.
O Apache mesmo, fomentou e desenvolveu diversos serviços e produtos. Sendo a base para produtos incriveis pagos.
VAREJO OPEN SOURCE
Poucas ações tem contríbuido mais com o varejo que o ACBR, projeto Open Source destinado a alavancar empresas no desenvolvimento de soluções para PDV e Self Checkout.
Conheço grandes player que trabalhei que a base de funcionamento do seu PDV é baseado no ACBR.
Apesar de termos um grande player, como o ACBR, existem poucas soluções Open Source destinadas ao Varejo.
Vamos falar de minhas soluções
Os projetos que desenvolvo, são sempre atrelados a Hardware, minha paixão.
Sempre que criei uma lib, ou desenvolvo conexão com um hardware, este pode e deve ser integrado, dentro de uma cadeia ou software house.
Vamos falar sobre alguns projetos:
O srvCP é um software (servidor) destinado a integrar com equipamentos de consulta de preço. Este por si só precisa de uma base de produtos, que deve ser integrada de um PDV ou CRM. Dificilmente um cliente entrega meu software sem ter um PDV ou CRM em sua loja.
Pois este precisa de uma base de produtos saneados.
Então, o srvCP não prejudica desenvolvedores de software, muito pelo contrário, agrega uma oportunidade, permitindo agregar o benefício de uso de leitores de preço sem a necessidade de desenvolvimento e manutenção deste equipamento.
Agora iremos falar sobre outro projeto o RFID, este projeto destinado a criar um leitor de RFID de mesa, não tem o objetivo de fornecer equipamentos para o varejo, ou atacadistas. Pois o seu desenvolvimento implica em assemblagem de equipamentos eletrônicos, bem como impressão. O que por fim acaba saindo mais caro que seus equipamentos industriais. Porem, este pode ser usado em ambientes de desenvolvimento, e equipes de TI, permitindo a simulação em seu PDV de cartões. Sem a real necessidade de compra de seus pares industrializados. O uso deste, permite aprimorar e desenvolver conceitos na indústria de software.
Outro exemplo, é o software de emissão de etiqueta, este projeto permite criar um serviço de impressão de etiquetas, permitindo a integração com o CRM, através de uma web api. Permitindo imprimir etiquetas de gondolas de forma fácil e transparente.
Por fim, iremos falar sobre o projeto Leitor Balança, este projeto visa criar um serviço de leitura de balança, que permite através de uma Web API ler o peso.
Vejam que os projetos Open Source são integrados e permitem integração, retirando das software houses a necessidade de desenvolvimento destes equipamentos, deixando elas se preocupar com seu real core business.
Vemos aqui, que projetos open source, são parceiros dos empreendedores, pois criam oportunidades de negócio, permitindo que estes foquem no que realmente é importante.
Com este texto, espero muito que as software house, percam o medo do desenvolvimento open source, e abracem a causa, pois este agrega oportunidades de negocio. Alavancando o negócio delas.
Neste estudo darei um exemplo de aplicação prática usando o OPENCV.
Este artigo faz parte do trabalho de pós graduação apresentado na disciplina de OpenCV, da UNINOVE.
RA dos Alunos:
621200322 – Marcelo Maurin Martins
621201522 – Aland Montano
621202498 – Luciano Braga
621200985 – Jhone Fontenele
622137013- Douglas Campos
Equipamento:
Para realizar este estudo comprei o VEIN DISPLAY INSTRUMENT ZY-500.
Caracteristicas:
800-1000nm infrared
IR 1080P
Diametro 48mm
Equipamento ZY-500
Como ele Funciona
Ele é basicamente uma webcam USB 2.0, com resolução de 1080 pixel.
Este equipamento emite uma luz infra vermelha, que parcialmente penetra na pele (derme), e é refletida.
Porem em áreas onde existe muito sangue, a luz infra vermelha é absorvida.
Sabendo disso, fica facil identificar as veias proximas da pele.
Abaixo vemos um vídeo onde demonstro a visualização da camera sem nenhum tratamento.
Demonstração em Vídeo
Aqui apresentaremos detalhes do funcionamento da camera.
Neste exemplo mostro a imagem pura, sem processamento
Podemos ver em uma câmera normal, que as veias não se destacam.
Web cam normal
Porem podemos ver exatamente as veias na camera infravermelha.
Nesta imagem, sem filtros, podemos ver as veias claramente.
Imagem sem filtros
Inicio do processo de desenvolvimento
A imagem acima foi obtida, através do processamento do seguinte script PYTHON.
Iremos aplicar as técnicas aprendidas no curso, para avaliar a viabilidade destas na aplicação da solução. Lembrando que como qualquer processo cientifico, a experimentação empírica faz parte do processo.
E nem todas as técnicas serão utilizadas no projeto final.
Exemplo de código em Python
import cv2
device = 5
captura = cv2.VideoCapture(device)
while(1):
ret, frame = captura.read()
cv2.imshow("Camera Detector Veia", frame)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
captura.release()
cv2.destroyAllWindows()
A máquina em questão possui diversos devices (Cameras) acopladas, porem o número pode subir pois scripts em python tem o estranho habito de travar, e as vezes é necessário desligar o dispositivo, e religalo, o que causa um incremento no numero do device devido ao travamento do recurso.
Este travamento é temporario.
Vendo a banda RED
Separando a banda RED e verificando a melhora.
No fragmento de código abaixo, seleciono apenas a banda RED do RGB, onde analiso se há mudança significativa.
O nosso código, já possui a técnica contendo o resultado final empregado.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Apr 15 16:00:05 2022
@author: mmm
"""
import cv2
#from PIL import Image
import numpy as np
import imutils
import pip
import importlib, os
from matplotlib import pyplot as plt
#import Image
from PIL import Image, ImageChops
global fundo
global frame
global gray1
global edged
global ret
device = 2
captura = cv2.VideoCapture(device)
while(1):
ret, frame = captura.read()
cv2.imshow("Camera Detector Veia", frame)
(B, G, R) = cv2.split(frame)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
num_lim = frame.shape[0]
num_col = frame.shape[1]
num_bandas = frame.shape[2]
gray2= np.zeros((num_lim , num_col), dtype="uint8")
gray2= B+G+R//3
#[num_lim, num_col, num_bandas] = frame.shape
dimensions = frame.shape
print('Image Dimension:',dimensions)
print('Image Height :',num_lim)
print('Image width:',num_col)
print('Image Channels:',num_bandas)
thresh = 135
fundo2 = cv2.threshold(gray,thresh,255,cv2.THRESH_BINARY)[1] #imagem limiralizada
#[thresh, fundo2] = cv2.threshold(gray, thresh, 255, cv2.THRESH_OTSU)
cv2.imshow("fundo2",fundo2)
img_filtro= np.zeros((num_lim , num_col, num_bandas), dtype="uint8")
for l in range(num_lim):
for c in range(num_col):
img_filtro[l,c] = ((fundo2[l,c]) & (frame[l,c] ^ fundo2[l,c]))
#img_filtro[l,c] = (frame[l,c] ^ fundo2[l,c])
#img_filtro = ImageChops.difference(fundo, frame)
cv2.imshow("filtrado", img_filtro)
while(1):
#gaus = cv2.GaussianBlur(img_filtro, (3, 3), 0)
#edged = cv2.Canny(img_filtro, 40, 103)
#janela = np.ones((3,3),np.float32)*-1
#palta = cv2.filter2D(img_filtro,-6,janela)
#gaus=cv2.GaussianBlur(img_filtro,(0,0),5)
#palta2=cv2.Scharr(img_filtro, ddepth=-1, dx=1, dy=0, scale=1, borderType=cv2.BORDER_DEFAULT)
#filtro = ImageChops.difference(fundo,gray)
#filtro = ImageChops.logical_xor(fundo,gray)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
RGB = cv2.cvtColor(img_filtro, cv2.COLOR_BGR2RGB)
grayold = gray
gray = cv2.cvtColor(RGB, cv2.COLOR_RGB2GRAY)
#gray = grayold
while(1):
cv2.imshow('gray',gray)
#http://www.lps.usp.br/hae/apostila/filtconv-ead.pdf
#Calculo de gradiente usando Scharr
schar=cv2.Scharr(gray, ddepth=-1, dx=0, dy=1, scale=1, borderType=cv2.BORDER_DEFAULT)
#cv2.imshow("gaus", gaus)
#cv2.imshow("Canny", edged)
cv2.imshow("Scharr", schar)
sobel=cv2.Sobel(schar,-2,1,1)
kernel = np.ones((5,5),np.uint8)
dilation = cv2.dilate(gray,kernel,iterations = 1)
maurin= np.zeros((num_lim , num_col), dtype="uint8")
for l in range(num_lim):
for c in range(num_col):
if(dilation[l,c]>=74 and dilation[l,c]<=76):
maurin[l,c] = 0
else:
maurin[l,c] = dilation[l,c]
thresh = 80
binimg=np.zeros((num_lim,num_col), dtype="uint8")
binimg=cv2.threshold(gray2, thresh, 255, cv2.THRESH_TOZERO)[1]
#cv2.imshow('gaus',gaus)
#cv2.imshow('edged',edged)
cv2.imshow('sobel',sobel)
cv2.imshow('dilation',dilation)
cv2.imshow('maurin:',maurin)
cv2.imshow('bin',binimg)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
captura.release()
cv2.destroyAllWindows()
Neste ultimo fragmento, iremos retirar o fundo do braço, e trabalhar com a imagem para dar destaque.
O resultado final é o que se apresenta.
Na imagem acima, podemos perceber que retiramos o braço dos demais objetos da imagem.
Tambem tratamos a imagem em tons de cinza, que permite posteriormente um trato mais simples da imagem.
Qual a vantagem da imagem acima da original. Primeiramente, a imagem original apesar de ser bem visivel a veia para nós, não conseguimos determinar um tom unico, para apresentar como veias. Na imagem processada, o tom da veia, esta mais distinto da imagem.
O que foi feito
Inicialmente capturamos a camera, através de um device.
Em seguida armazenamos a imagem na variavel frame.
Convertemos a imagem em cinza, através do comando:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
Agora, feita a primeira conversão, iremos pegar as caracteristicas da imagem, através da propriedade shape.
As propriedades de Altura (Height), Width( Largura) e channel (numero de bandas).
Agora iremos separar o braço do fundo, através da Limiarização:
O Filtro de dilatação, torna as marcas das veias mais marcantes.
Dilatation
Sua sintaxe é conforme apresentada.
Dando um incremento a visão da veia.
dilation = cv2.dilate(gray,kernel,iterations = 1)
Por fim apresentamos o vídeo final.
Vídeo detector de veias
Conclusão
Este estudo demonstra que através de técnicas de manipulação de imagem, sem o uso de redes neurais conseguimos trabalhar com imagens, realçando e separando partes que desejamos trabalhar.
Outra parte importante, é a associação de operações:
Onde associamos o fundo da imagem com a imagem, a fim da extração do fundo e aplicação do formato RGB, desassociado ao fundo.
Concomitante com o uso do Dilate (filtro de dilatação) associado ao Scharr, apresentou ótimos resultados, conforme apresentado a seguir.
Associação do Dilate associado ao Scharr, apresentou ótimo resultado.
Tendo como resultado final o código gerado:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Apr 15 16:00:05 2022
@author: mmm
"""
import cv2
#from PIL import Image
import numpy as np
import imutils
import pip
import importlib, os
from matplotlib import pyplot as plt
#import Image
from PIL import Image, ImageChops
global fundo
global frame
global gray1
global edged
global ret
device = 2
captura = cv2.VideoCapture(device)
while(1):
ret, frame = captura.read()
cv2.imshow("Camera Detector Veia", frame)
(B, G, R) = cv2.split(frame)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
num_lim = frame.shape[0]
num_col = frame.shape[1]
num_bandas = frame.shape[2]
gray2= np.zeros((num_lim , num_col), dtype="uint8")
gray2= B+G+R//3
#[num_lim, num_col, num_bandas] = frame.shape
dimensions = frame.shape
print('Image Dimension:',dimensions)
print('Image Height :',num_lim)
print('Image width:',num_col)
print('Image Channels:',num_bandas)
thresh = 135
fundo2 = cv2.threshold(gray,thresh,255,cv2.THRESH_BINARY)[1] #imagem limiralizada
#[thresh, fundo2] = cv2.threshold(gray, thresh, 255, cv2.THRESH_OTSU)
cv2.imshow("fundo2",fundo2)
img_filtro= np.zeros((num_lim , num_col, num_bandas), dtype="uint8")
for l in range(num_lim):
for c in range(num_col):
img_filtro[l,c] = ((fundo2[l,c]) & (frame[l,c] ^ fundo2[l,c]))
#img_filtro[l,c] = (frame[l,c] ^ fundo2[l,c])
#img_filtro = ImageChops.difference(fundo, frame)
cv2.imshow("filtrado", img_filtro)
while(1):
#gaus = cv2.GaussianBlur(img_filtro, (3, 3), 0)
#edged = cv2.Canny(img_filtro, 40, 103)
#janela = np.ones((3,3),np.float32)*-1
#palta = cv2.filter2D(img_filtro,-6,janela)
#gaus=cv2.GaussianBlur(img_filtro,(0,0),5)
#palta2=cv2.Scharr(img_filtro, ddepth=-1, dx=1, dy=0, scale=1, borderType=cv2.BORDER_DEFAULT)
#filtro = ImageChops.difference(fundo,gray)
#filtro = ImageChops.logical_xor(fundo,gray)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
RGB = cv2.cvtColor(img_filtro, cv2.COLOR_BGR2RGB)
grayold = gray
gray = cv2.cvtColor(RGB, cv2.COLOR_RGB2GRAY)
#gray = grayold
while(1):
cv2.imshow('gray',gray)
#http://www.lps.usp.br/hae/apostila/filtconv-ead.pdf
#Calculo de gradiente usando Scharr
schar=cv2.Scharr(gray, ddepth=-1, dx=0, dy=1, scale=1, borderType=cv2.BORDER_DEFAULT)
#cv2.imshow("gaus", gaus)
#cv2.imshow("Canny", edged)
cv2.imshow("Scharr", schar)
sobel=cv2.Sobel(schar,-2,1,1)
kernel = np.ones((5,5),np.uint8)
#dilation = cv2.dilate(gray,kernel,iterations = 1)
dilation = cv2.dilate(schar,kernel,iterations = 1)
maurin= np.zeros((num_lim , num_col), dtype="uint8")
for l in range(num_lim):
for c in range(num_col):
if(dilation[l,c]>=74 and dilation[l,c]<=76):
maurin[l,c] = 0
else:
maurin[l,c] = dilation[l,c]
thresh = 80
binimg=np.zeros((num_lim,num_col), dtype="uint8")
binimg=cv2.threshold(gray2, thresh, 255, cv2.THRESH_TOZERO)[1]
#cv2.imshow('gaus',gaus)
#cv2.imshow('edged',edged)
cv2.imshow('sobel',sobel)
cv2.imshow('dilation',dilation)
cv2.imshow('maurin:',maurin)
cv2.imshow('bin',binimg)
k = cv2.waitKey(30) & 0xff
if k == 27:
break
captura.release()
cv2.destroyAllWindows()
Neste trabalho, podemos verificar que ainda é longo e árduo o trabalho que separa o pré processamento da imagem, bem como não se trata de um trabalho acabado. Há muitas técnicas aqui não empregadas, que poderiam ser ajustadas.
Porem a analise que foi feita em várias das técnicas apresentadas durante o curso, tiveram resultados significativos na identificação e destaque das veias.
Agradecimento especial ao Professor Sidnei Alves de Araujo, da UNINOVE, que incentivou e permitiu a execução de trabalho especial.