week 5 ++ pixel neighbors

solving the edge problem (code) : so I was initially trying this with a complicated set of extra variables (I think I often do this because I like to have the freedom of doing dynamic stuff with a set of variables) but the min/max idea was pretty elegant so I stuck with that. this example uses a basic gaussian blur

/* in the setup() */

for (int i = 0; i < imageW - 0; i++){
	for (int j = 0; j < imageH - 0; j++){
		
		// drawing inside the lines...
		int nw = pixelsA[MAX(j - 1, 0	  )		* imageW + MAX(i - 1, 0			)];
		int n_ = pixelsA[MAX(j - 1, 0	  )		* imageW + (i					)];
		int ne = pixelsA[MAX(j - 1, 0	  )		* imageW + MIN(i + 1, imageW - 1)];
		int w_ = pixelsA[(j				  )		* imageW + MAX(i - 1, 0			)];
		int me = pixelsA[(j				  )		* imageW + (i					)];
		int e_ = pixelsA[(j				  )		* imageW + MIN(i + 1, imageW - 1)];
		int sw = pixelsA[MIN(j + 1, imageH - 1) * imageW + MAX(i - 1, 0			)];
		int s_ = pixelsA[MIN(j + 1, imageH - 1) * imageW + (i					)];
		int se = pixelsA[MIN(j + 1, imageH - 1) * imageW + MIN(i + 1, imageW - 1)];
		
		
		float newVal = (nw * kernel[0] + n_ * kernel[1] + ne * kernel[2] + 
						w_ * kernel[3] + me * kernel[4] + e_ * kernel[5] + 
						sw * kernel[6] + s_ * kernel[7] + se * kernel[8]) / kernelWeight;
		
		
		newVal = MIN(MAX(newVal, 0), 255);
		
		pixelsB[(j  ) * imageW + (i  )] = newVal;
	}
}
				

edge detection cases (code) : playing around with different edge detection with compounded kernels (4-direction and 8-direction).

so the first set of images shows that the 8-direction edge detection (right) actually doesn't work as well as the 4-direction one (center), because the edges are restricted to certain directions, so looking at all directions averages out the important edges.

the second set of images shows that 8-direction (right) works best with images of edges in all or many directions.



/* in the setup() */
/* this is the main chunk of code */
				
float newVals[8];
			
// -- 4x kernel averaging --
float finalVal_4 = 0;
for (int nv = 0; nv < 2; nv++){
	newVals[nv] = (nw * kernels[nv][0] + n_ * kernels[nv][1] + ne * kernels[nv][2] + 
				   w_ * kernels[nv][3] + me * kernels[nv][4] + e_ * kernels[nv][5] + 
				   sw * kernels[nv][6] + s_ * kernels[nv][7] + se * kernels[nv][8]) / kernelWeight;

	newVals[nv] = MIN(MAX(newVals[nv], 0), 255);
	finalVal_4 += newVals[nv];
}				 
finalVal_4 = finalVal_4/2;
pixelsB[j * imageW + i] = finalVal_4;

// -- 8-directional kernel averaging --
float finalVal_8 = 0;
for (int nv = 0; nv < 8; nv++){
	newVals[nv] = (nw * kernels[nv][0] + n_ * kernels[nv][1] + ne * kernels[nv][2] + 
				   w_ * kernels[nv][3] + me * kernels[nv][4] + e_ * kernels[nv][5] + 
				   sw * kernels[nv][6] + s_ * kernels[nv][7] + se * kernels[nv][8]) / kernelWeight;

	newVals[nv] = MIN(MAX(newVals[nv], 0), 255);
	finalVal_8 += newVals[nv];
}				 
finalVal_8 = finalVal_8/8;
pixelsC[j * imageW + i] = finalVal_8;
				


advanced drawing tool (code) : so here I've got it loading an image, and doing adding ome drawing mechanism (noisy, cyclic grayscale brush). seems like a pretty intense drawing tool (intense on memory), but could definitely come up with some nice real-time effects



for (int i = 0; i < imageW - 0; i++){
	for (int j = 0; j < imageH - 0; j++){
		
		// drawing inside the lines...
		int nw = pixelsC[MAX(j - 1, 0	  )		* imageW + MAX(i - 1, 0			)];
		int n_ = pixelsC[MAX(j - 1, 0	  )		* imageW + (i					)];
		int ne = pixelsC[MAX(j - 1, 0	  )		* imageW + MIN(i + 1, imageW - 1)];
		int w_ = pixelsC[(j				  )		* imageW + MAX(i - 1, 0			)];
		int me = pixelsC[(j				  )		* imageW + (i					)];
		int e_ = pixelsC[(j				  )		* imageW + MIN(i + 1, imageW - 1)];
		int sw = pixelsC[MIN(j + 1, imageH - 1) * imageW + MAX(i - 1, 0			)];
		int s_ = pixelsC[MIN(j + 1, imageH - 1) * imageW + (i					)];
		int se = pixelsC[MIN(j + 1, imageH - 1) * imageW + MIN(i + 1, imageW - 1)];
		
		
		// -- 4x kernel averaging --
		float newVals[8];
		float finalVal = 0;
		for (int nv = 3; nv < 4; nv++){
			newVals[nv] = (nw * kernels[nv][0] + n_ * kernels[nv][1] + ne * kernels[nv][2] + 
						   w_ * kernels[nv][3] + me * kernels[nv][4] + e_ * kernels[nv][5] + 
						   sw * kernels[nv][6] + s_ * kernels[nv][7] + se * kernels[nv][8]) / kernelWeight;
		
			newVals[nv] = MIN(MAX(newVals[nv], 0), 255);
			finalVal += newVals[nv];
		}				 
		
		
		/* -- drawing -- */
		
		float diffx = (mouseX - i);
		float diffy = (mouseY - j);
		float ran = ofRandomuf();
		float dist = sqrt(diffx*diffx + diffy*diffy) + 80*ran;
		
		//float ran = ofRandomuf();
		//float ran2 = ofRandomuf(); 
		float dist_var = 60;
		
		float draw = 128 * (1 + sin(float(time) / 30));
		
		if (dist < dist_var){
			finalVal = MIN(MAX(draw, 0), 255); 
		}
		/*else {
			//finalVal = ;
		}*/
		
		
		pixelsB[j * imageW + i] = finalVal;
	}
}

				


conway's life (code) : standard recreation of conway's life. I used a random noise generator to populate at first. Also, there are two scrolling histograms plotting the total 'live' cells and the total moving cells (went from black to white). I tried playing around with the automata rules and sure enough slight variations produce pretty uninteresting stuff.



time++;
if(time == 1000){
	time = 0;
}
int total_moved = 0;
int total_live = 0;

for (int n = 0; n < imageW*imageH; n++){
	pixelsC[n] = pixelsB[n];
}


for (int i = 0; i < imageW - 0; i++){
	for (int j = 0; j < imageH - 0; j++){
		
		// drawing inside the lines...
		int dir[8];
		dir[0] = pixelsC[MAX(j - 1, 0	  )		* imageW + MAX(i - 1, 0			)];
		dir[1] = pixelsC[MAX(j - 1, 0	  )		* imageW + (i					)];
		dir[2] = pixelsC[MAX(j - 1, 0	  )		* imageW + MIN(i + 1, imageW - 1)];
		dir[3] = pixelsC[(j				  )		* imageW + MAX(i - 1, 0			)];
		int me = pixelsC[(j				  )		* imageW + (i					)];
		dir[4] = pixelsC[(j				  )		* imageW + MIN(i + 1, imageW - 1)];
		dir[5] = pixelsC[MIN(j + 1, imageH - 1) * imageW + MAX(i - 1, 0			)];
		dir[6] = pixelsC[MIN(j + 1, imageH - 1) * imageW + (i					)];
		dir[7] = pixelsC[MIN(j + 1, imageH - 1) * imageW + MIN(i + 1, imageW - 1)];
		

		// count number of neighboring live cells
		int live = 0;		
		for (int d = 0; d < 8; d++){
			if(dir[d] == 255){
				live++;
			}
		}
		
		
		// decide who lives and who dies
		if(me == 0 && live == 3){							
				me = 255;									// frankencell, come to life!!!
		}else if(me == 255 && (live == 3 || live == 2)){
				me = 255;									// stay alive no matter what it takes...
		}else{								
				me = 0;										// squished or lonely
		}
		
		
		// count moving cells
		if(me == 255 && pixelsB[j * imageW + i] == 0){
			total_moved++;
		}
		
		
		pixelsB[j * imageW + i] = me;
	}
}

// count TOTAL number of neighboring live cells
for(int n = 0; n < imageH*imageW; n++){
	if(pixelsB[n] == 255){
		total_live++;
	}
}
living[time] = total_live;
moving[time] = total_moved;