image_analysis_code

code format="java" /** * Image loading Example * by George Showman * Created: Feb. 25th, 2006 * * 1. Load the image (put it in the right directory first, etc.) * 2. Filter the image... * 3. Analyze the image? * * CONTENTS OF THIS FILE: * - various global declarations * - usual setup and draw functions * - new vector analysis code, including Node class, DXF export * - new UI code, covering mouse and keyboard events * */

// gshowman: Control library import controlP5.*; ControlP5 controlP5; public int sliderValue = 3; ControlWindow controlWindow; Controller AnalyzeButton;

//make DXF import processing.dxf.*; boolean g_exportDXF;

// gshowman: control variables float match_factor = 0.75; float node_scalefactor = 0.3; int g_search_radius = 15; int g_button_pressed = 0; // duplicate of screen state color[] g_pixbuffer; int g_switch = -1; int g_button_count = 4; boolean g_analyze = false; boolean g_resume = false; boolean g_show_nodes = false; boolean g_z_mode = false; boolean paused = false; color g_search_color = color(0,0,0); // this is black boolean g_clear_the_list = false;

// gshowman: a list of all analytic Nodes we are creating Vector node_list = new Vector;

void setup { size(500, 500,P3D); frameRate(24); clearscr;

g_button_count = 3; g_analyze = false; g_resume = false; g_exportDXF = false; node_list = new Vector;

// one function to do all this load_and_prep_the_image;

// gshowman -- define all those UI buttons controlP5 = new ControlP5(this); controlWindow = controlP5.addControlWindow("controlP5window",100,100,400,200); controlWindow.setBackground(color(40)); Controller radiusSlider = controlP5.addSlider("g_search_radius",0,20,40,40,100,10); radiusSlider.setWindow(controlWindow); Controller matchSlider = controlP5.addSlider("match_factor",0.0,1.0,144,40,100,10); matchSlider.setWindow(controlWindow);

AnalyzeButton = controlP5.addButton("Analyze",0,40,100,80,20); AnalyzeButton.setWindow(controlWindow); Controller SaveFrameButton = controlP5.addButton("Clear_Analysis",1,124,100,80,20); SaveFrameButton.setWindow(controlWindow); Controller ExportDXFButton = controlP5.addButton("Export_DXF",2,208,100,80,20); ExportDXFButton.setWindow(controlWindow); Controller ShowNodesButton = controlP5.addButton("Show_Nodes",2,40,124,80,20); ShowNodesButton.setWindow(controlWindow); Controller ZModeButton = controlP5.addButton("Z_Mode",2,124,124,80,20); ZModeButton.setWindow(controlWindow); g_pixbuffer = new color[width*height]; }

void draw { controlP5.draw; if (g_analyze) { // run the analysis. println ("Running the vector analysis..."); vectorize(g_search_color);

paused = true; g_analyze = false; }

if (g_clear_the_list) { node_list.clear; g_clear_the_list = false; }

if (g_resume) { // we're going to re-start -- let's re-load the state prior // to vectorization println("re-instating conditions prior to analysis");

load_and_prep_the_image; /*clearscr; for (int i=0; i < width*height; i++) { w.setpix((i)%width, int ((i)/height), g_pixbuffer[i]); } */

paused = false; g_resume = false; }

if (paused) { // draw the analysis (just once) draw_connections; } else { // (this is the default state of the system)

}

// note: so when paused == true, nothing happens }

void clearscr { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) {

set(x, y, color(0)); } } }

void load_and_prep_the_image { // load the image PImage I = loadImage("barca_01.jpg");

// show the image on the screen image(I,0,0, width, height);

// filter the image filter(GRAY); filter(POSTERIZE, 4);

}

// // ANALYSIS CODE (new stuff by gshowman and fbitonti) //

//NODE class Node { int x, y, z, radius;

Node (int xin, int yin, int rad) { x = xin; y = yin; radius = rad; z = rad; // yes... the 'rad' is really an abstractd 'intensity', which can // be interpreted as a z-coordinate }

void draw_radius { stroke(255,50,0,150); noFill; ellipse(x, y, radius*node_scalefactor, radius*node_scalefactor); } }

// This is plain old Java Object-Oriented funkiness. Read up about // the Java Vector class, Collections, etc. if you want to understand. class NodeComparer implements Comparator { public int compare(Object n1, Object n2) { return ((Node) n1).radius - ((Node) n2).radius; } }

// takes a single pixel location, a search radius, and a color to match int find_matches_within(int xx, int yy, int radius, color c) { int matches = 0; int x = 0; int y = 0;

int xlim = min(width, xx+radius); int ylim = min(height, yy+radius);

for (x = max(0,xx-radius); x < xlim; x++) { for (y = max(0,yy-radius); y < ylim; y++) { if (get(x,y) == c) { matches++; } } }

return matches; }

//nodes are created void create_node(int x, int y, int intensity) { Node A = new Node(x,y,intensity); node_list.add(A); }

void vectorize(color c) { int x = 0; int y = 0;

// 1. take a copy of the current state. /*for (int i = 0; i < width*height; i++) { g_pixbuffer[i] = w.getpix(i%width, int (i/height)); }*/

int radius = g_search_radius; int match_limit = int(match_factor * (PI) * radius*radius);

for (x=0; x < width; x++) { for (y=0; y < height; y++) {

if (get(x,y) == c) { int matches = 0; //match -- check your neighbors matches += find_matches_within(x, y, radius, c); if (matches >= match_limit) { create_node(x, y, matches); println ("Created Node at " + x + ", " + y + " with intensity " + matches); } }

} } }

void draw_connections { //DXF export... begin recording geometry if (g_exportDXF) { beginRaw("processing.dxf.RawDXF", "C:\\output.dxf"); }

int nodeListSize = node_list.size ; int[] connectionArray = new int[nodeListSize]; int[] connectionArrayX = new int[nodeListSize]; int[] connectionArrayY = new int[nodeListSize]; int connectCount = 0;

// gshowman: sort the vector by intensity Collections.sort(node_list, new NodeComparer);

// Connect all nodes in descending order of intensity/radius stroke(255,50,0,150);

int last_x = 0; int last_y = 0; int last_z = 0;

if (!node_list.isEmpty) { Iterator it = node_list.iterator ; Node N = (Node) it.next; last_x = N.x; last_y = N.y; last_z = N.z;

if (g_show_nodes) { N.draw_radius; }

while (it.hasNext) { Node nextNode = (Node) it.next ; if (g_z_mode) { // use intensity as z-coordinate line(last_x, last_y, last_z, nextNode.x, nextNode.y, nextNode.z); } else { line(last_x, last_y, nextNode.x, nextNode.y); }

last_x = nextNode.x; last_y = nextNode.y; last_z = nextNode.z;

if (g_show_nodes) { nextNode.draw_radius; } } }

//dxf End recording if (g_exportDXF) { endRaw; g_exportDXF = false; } }

// // UI CODE //

void mousePressed { setup; }

void Analyze(int theIrrelevantValue) { println("Analyze button has been pressed..."); // For some reason the button gets pressed at startup... ignore that: if (g_button_count > 0) { g_button_count--; return; }

if (paused) { // raise the flag to end the analysis (see draw function) g_resume = true; AnalyzeButton.setLabel("Analyze"); } else { // raise the flag for the analysis (see the draw function) g_analyze = true; AnalyzeButton.setLabel("Resume"); } }

void Clear_Analysis(int theIrrelevantValue) { println("Clear_Analysis button has been pressed..."); // For some reason the button gets pressed at startup... ignore that: if (g_button_count > 0) { g_button_count--; return; }

// just empty the node_list g_clear_the_list = true; }

void Export_DXF(int theIrrelevantValue) { println("Export_DXF button has been pressed..."); // For some reason the button gets pressed at startup... ignore that: if (g_button_count > 0) { g_button_count--; return; }

g_exportDXF = true; }

void Show_Nodes(int theIrrelevantValue) { println("Show_Nodes button has been pressed..."); // For some reason the button gets pressed at startup... ignore that: if (g_button_count > 0) { g_button_count--; return; }

if (g_show_nodes) { g_show_nodes = false; println("Turning nodes off"); } else { g_show_nodes = true; println("Turning nodes on"); } }

void Z_Mode(int theIrrelevantValue) { println("Z_Mode button has been pressed..."); // For some reason the button gets pressed at startup... ignore that: if (g_button_count > 0) { g_button_count--; return; }

if (g_z_mode) { g_z_mode = false; println("Turning Z_Mode off"); } else { g_z_mode = true; println("Turning Z_Mode on"); } }

code