Programme de traitement sélectif de l’image d’une caméra de smartphone ou tablette Android.
Sélection de la couleur au touché et suivi en temps réel.Le traitement débute au lancement de la caméra. La plage de sélection s’effectue grâce à un ascenseur de seuil et le menu permet de permuter entre caméra frontal et arrière et d’utiliser le flash.
L’interface affiche un retour sur le pourcentage de pixels colorés sélectionnés.
Source: detectorColorProcessingAndroid.pde / Processing 3.5.3 + Android mode + librairie Ketai
import ketai.camera.*;
KetaiCamera camD;
PGraphics container;
PImage camImage;
boolean onFrontCam, switchCam;
int camWidth, camHeight;
int pixelColorX, pixelColorY;
boolean trackingPixelColor, tresholdColorCursor;
color targetColor;
int colorTreshold;
int pixelTreshold;
PVector tresholdCursor = new PVector(0,0);
int nbTotalPixels;
float nbMaxPixels;
float nbMinPixels;
float nbPixels;
float pourcent;
int startTimer;
int timerSwitchCam;
int refresh;
int refreshSwitchCam;
String texte1 = "";
String texte2 = "";
int textSize;
int UITop, UIBottom, UIRight;
void setup(){
fullScreen();
orientation(LANDSCAPE);
imageMode(CENTER);
frameRate(30);
camWidth = 1280;
camHeight = 720;
camD = new KetaiCamera(this, camWidth, camHeight, 24);
camD.setCameraID(0);
rectMode(CORNER);
imageMode(CORNER);
onFrontCam = false;
switchCam = true;
trackingPixelColor = false;
colorTreshold = 40;
targetColor = color(255, 153, 0); // color(190, 130, 70);
textSize = 40;
textSize(textSize);
fill(targetColor);
UIBottom = textSize*3;
UITop = textSize+40;
UIRight = textSize*2;
nbTotalPixels = camWidth*camHeight;
pixelTreshold = 1; // seuil en pixels de traitement de la video
nbMaxPixels = nbTotalPixels*0.6; // pourcentage max: 60%
nbMinPixels = nbTotalPixels*0.2; // pourcentage min: 20%
refresh = 5000; // delai photo nbPixels > nbMaxPixels
refreshSwitchCam = 10000;
timerSwitchCam = millis() + refreshSwitchCam;
startTimer = millis() + refresh;
}
void timerCamRefresh(){
timerSwitchCam = millis() + refreshSwitchCam;
}
void draw(){
background(0);
if (camD != null) {
texte1 = "< ... >";
if(trackingPixelColor){
pixelColorX = int(map(mouseX, 0, width, 0, camWidth));
pixelColorY = int(map(mouseY, 0, height, 0, camHeight));
camD.loadPixels();
targetColor = camD.get(pixelColorX, pixelColorY);
fill(targetColor);
image(camD, 0, 0, width, height);
texte2="<SearchColor> <R: " + red(targetColor) + " / G: " + green(targetColor) + " / B: " + blue(targetColor) + ">";
rect(0, UITop, 100, 100);
}else{
texte2="<SearchPixels><tresholdColor: " + colorTreshold + "><" + nbPixels + " / " + nbTotalPixels + "> <" + pourcent*100 + "%>";
nbPixels = 0;
camD.loadPixels();
container = createGraphics(camWidth, camHeight);
container.beginDraw();
container.noStroke();
for (int y = 0; y < camHeight-pixelTreshold; y=y+pixelTreshold) {
for (int x = 0; x < camWidth-pixelTreshold; x=x+pixelTreshold) {
color pixelColor = camD.get(x, y);
if (red(pixelColor) > red(targetColor)-colorTreshold && red(pixelColor) < red(targetColor)+colorTreshold &&
green(pixelColor) > green(targetColor)-colorTreshold && green(pixelColor) < green(targetColor)+colorTreshold &&
blue(pixelColor) > blue(targetColor)-colorTreshold && blue(pixelColor) <blue(targetColor)+colorTreshold) {
nbPixels += pixelTreshold*pixelTreshold;
container.fill(targetColor);
container.rect(x-pixelTreshold, y-pixelTreshold, pixelTreshold*2, pixelTreshold*2);
}
}
}
pourcent = nbPixels/nbTotalPixels;
if(pourcent > 0.1){
texte1="<colorDetected>";
}else{
texte1="<...>";
}
container.endDraw();
image(camD, 0, 0, width, height);
image(container, 0, 0, width, height);
}
}
drawUI();
}
void onCameraPreviewEvent() {
camD.read();
}
void mousePressed(){
//touch screen color selection
if(mouseY > UITop && mouseY < height - UIBottom && mouseX < width - UIRight){
trackingPixelColor = true;
}else{
trackingPixelColor = false;
}
//cursor color treshold
if(mouseX > width-UIRight && mouseY > UITop && mouseY < height-(UITop + UIBottom)){
tresholdColorCursor = true;
}else{
tresholdColorCursor = false;
}
//menu 1
if (mouseX < width/5 && mouseY < 40){
if (camD.isStarted()){
camD.stop();
}else{
camD.start();
}
}
//menu 2
if (mouseX < 2*width/5 && mouseX > width/5 && mouseY < 40){
if (camD.getNumberOfCameras() > 1){
camD.setCameraID((camD.getCameraID() + 1 ) % camD.getNumberOfCameras());
}
}
//menu 3
if(mouseX > 2*width/5 && mouseX < 3*width/5 && mouseY < 40){
if (camD.isFlashEnabled()){
camD.disableFlash();
}else{
camD.enableFlash();
}
}
//menu 4
if(mouseX > 3*width/5 && mouseX < 4*width/5 && mouseY < 40){
}
//menu 5
if(mouseX > 4*width/5 && mouseY < 40){
}
}
void mouseReleased(){
if(trackingPixelColor){
trackingPixelColor = false;
}
}
void drawUI()
{
pushStyle();
textAlign(CENTER);
int textSpace = width/10;
fill(0);
rect(0, 0, width, UITop);
fill(200);
text("|", 2*textSpace, 3*UITop/4);
text("|", 4*textSpace, 3*UITop/4);
text("|", 6*textSpace, 3*UITop/4);
text("|", 8*textSpace, 3*UITop/4);
if (camD.isStarted()){
text("Camera Off", textSpace, 3*UITop/4);
}else{
text("Camera On", textSpace, 3*UITop/4);
}
if (camD.getNumberOfCameras() > 0){
text("Switch Camera", 3*textSpace, 3*UITop/4);
}
if (camD.isFlashEnabled()){
text("Flash Off", 5*textSpace, 3*UITop/4);
}else{
text("Flash On", 5*textSpace, 3*UITop/4);
}
// treshold cursor
fill(0);
rect(width-UIRight, UITop, UIRight, height-(UITop + UIBottom));
tresholdCursor.x = width-UIRight;
if(tresholdColorCursor){
tresholdCursor.y = mouseY;
colorTreshold = int(map(tresholdCursor.y, UITop, height-(UITop + UIBottom), 0, 100));
}else{
tresholdCursor.y = int(map(colorTreshold, 0, 100, UITop, height-(UITop + UIBottom)));
}
fill(200);
rect(tresholdCursor.x, tresholdCursor.y, UIRight, UIRight);
//Infos
fill(0);
rect(0, height-UIBottom, width, UIBottom);
fill(200);
rect(0, height-UIBottom, width*pourcent, 30);
textAlign(CORNER);
text(texte1, 27, height-textSize);
text(texte2, 27, height);
popStyle();
}
Be First to Comment