Making random rectangles on Processing - java

I want to make random rectangles on Processing. So far, I used for loops for making window size rectangle but I can't figure out how to make only 10 rectangle randomly. Here is my sample code for you:
void setup()
{
size(400, 400);
}
void draw()
{
background(0); // Black Background
stroke(255); // White lines
for (int j = 0; j <= height; j += 40)
{
for (int i = 0; i < width; i += 40)
{
fill(0);
rect(i, j, 40, 40);
}
}
}
It shows 100 black rectangles but I want to see only 10 black rectangles. For example: The first line will get random 1 rectangle, second line will get 2 , third line will get 1 and it goes till the 10.

There are multiple ways to solve this fun homework/exercise.
First thing is drawing the right number of boxes per column:
void setup()
{
size(400, 400);
background(0); // Black Background
fill(0);
stroke(255); // White lines
int boxSize = 40;
int maxBoxes = 1;
for (int j = 0; j <= height; j += boxSize)
{
// box count per row
int boxCount = 0;
for (int i = 0; i < width; i += boxSize)
{
// only draw the max number of boxes
if(boxCount < maxBoxes){
rect(i, j, 40, 40);
// increment per row box count
boxCount++;
}
}
// increment max boxes per box
maxBoxes++;
}
}
Secondly the positions for the drawn boxes per column need to be randomized, but ideally not overlap. One option is to split the full solution space to sections: each section having it's own range of positions so it won't overlap the next.
void setup()
{
size(400, 400);
background(0); // Black Background
fill(0);
stroke(255); // White lines
int boxSize = 40;
int maxBoxes = 1;
int totalBoxes = width / boxSize;
for (int j = 0; j <= height; j += boxSize)
{
// box count per row
int boxCount = 0;
// a list of box indices of where to draw a box (as opposed
int[] randomXIndices = new int[maxBoxes];
// how many index ranges to span per row
int indexRangePerBox = totalBoxes / maxBoxes;
// for each random index
for(int k = 0 ; k < maxBoxes; k++)
{
// pre-calculate which random index to select
// using separate ranges per box to avoid overlaps
randomXIndices[k] = (int)random(indexRangePerBox * k, indexRangePerBox * (k + 1));
}
for (int i = 0; i < width; i += boxSize)
{
// only draw the max number of boxes
if(boxCount < maxBoxes)
{
int randomX = randomXIndices[boxCount] * boxSize;
rect(randomX, j, 40, 40);
// increment per row box count
boxCount++;
}
}
// increment max boxes per box
maxBoxes++;
}
}
void draw(){
}
void mousePressed(){
setup();
}
Click to reset. Notice that the bottom rows almost always look the same:
there is less wiggle room to pick a random position
random() is a rough pseudo-random number generator, but there are better ones out there like randomGaussian(), noise(), etc.
overall there are other strategies to explore picking random positions and avoiding overlaps
Live demo bellow:
function setup()
{
createCanvas(400, 400);
reset();
// reset once per second
setInterval(reset, 1000);
}
function reset(){
background(0); // Black Background
fill(0);
stroke(255); // White lines
var boxSize = 40;
var maxBoxes = 1;
var totalBoxes = width / boxSize;
for (var j = 0; j <= height; j += boxSize)
{
// box count per row
var boxCount = 0;
// a list of box indices of where to draw a box (as opposed
var randomXIndices = new Array(maxBoxes);
// how many index ranges to span per row
var indexRangePerBox = totalBoxes / maxBoxes;
// for each random index
for(var k = 0 ; k < maxBoxes; k++)
{
// pre-calculate which random index to select
// using separate ranges per box to avoid overlaps
randomXIndices[k] = floor(random(indexRangePerBox * k, indexRangePerBox * (k + 1)));
}
for (var i = 0; i < width; i += boxSize)
{
// only draw the max number of boxes
if(boxCount < maxBoxes)
{
var randomX = randomXIndices[boxCount] * boxSize;
rect(randomX, j, 40, 40);
// increment per row box count
boxCount++;
}
}
// increment max boxes per box
maxBoxes++;
}
}
function draw(){
}
function mousePressed(){
reset();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>

Related

How to animate a tiled grid in Processing

I am currently trying to create a grid of tiles in PROCESSING.... and I want each tile to appear after the other. (First row, left to right, second row, left to right and so on).... I get it to make each row of tiles appear one by one by a combination of frameCount and modulo in the nested loop.... but how to let each tile appear after another?
I've tried using the same method on the x-axis loop - this makes the grid appear from LEFT/UP to RIGHT/DOWN.... I tried changing the frameCount by multiplying times 10.... but this doesn't seem to be the correct maths.... do I need to use a conditional statement on one of the loops? Like if tiles is equal times round second row, third and so on? This is what I came up with so far:
void setup() {
size(500, 500);
}
void draw() {
background(255);
rectMode(CENTER);
float tiles = 10;
float tileSize = width/tiles;
translate(tileSize/2, tileSize/2);
for (int x = 0; x < tiles; x++) {
for (int y = 0; y < frameCount/tiles % tiles; y++) {
fill(0, 255, 0);
rect(x*tileSize, y*tileSize, tileSize, tileSize);
}
}
}
Thank you for any kind of help or hint!
My Processing is broken for some reason, you can past the following code to the p5js online editor
Is this what you want?
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
let tiles = 10;
let tileSize = width/tiles;
for(let y = 0; y < tiles; y++){
for(let x = 0; x < tiles; x++){
if(x + 10*y < frameCount)
rect(x*tileSize, y*tileSize, tileSize, tileSize)
}
}
}
https://editor.p5js.org/

Redraw selected area of pixels around the current pixel in processing

I'm new to processing. I'm trying to change the color(or another parameter like hue, saturation..) of the pixels around every pixel.
I get nothing changed instead of desired result. Please, help anybody (+
PImage imgg;
void setup() {
size(250,166);
imgg = loadImage("input.jpg");
loadPixels();
image(imgg,0,0);
}
void draw() {
for (int i = 0; i < imgg.width; i++) {
for (int j = 0; j < imgg.height; j++) {
//get the brightness value of the current pixel
int Bright_coeff = int(brightness(pixels[j*imgg.width+i]));
//calculate the area around the current pixel
int Bright_dist = Bright_coeff/10 ;
//area around that pixel will update its color
for (int x = 0; x < imgg.width; x++ ){
for (int y = 0; y < imgg.height; y++){
//check if the distance between iterating pixels and current pixel from above cycle is less than Bright_dist
if ( dist(x, y, i, j)<Bright_dist ){
color qwerty = color(random(1,255),random(1,255),random(1,255)) ;
pixels[y*imgg.width+x] = qwerty;
updatePixels();
}else {
updatePixels();
}
}
}
}
}
}
loadPixels() loads the pixel data of the current display window.
loadPixels has to be done, after the image is drawn to the window by image():
PImage imgg;
void setup() {
size(128,128);
imgg = loadImage("input.jpg");
image(imgg,0,0);
loadPixels();
}
The display is just updated once, after draw() has been executed. updatePixels() set the pixel data for the display window. It is sufficient to do that once at the end of draw():
void draw() {
// [...]
updatePixels();
}

Implementing a License plate detection algorithm

To improve my knowledge of imaging and get some experience working with the topics, I decided to create a license plate recognition algorithm on the Android platform.
The first step is detection, for which I decided to implement a recent paper titled "A Robust and Efficient Approach to License Plate Detection". The paper presents their idea very well and uses quite simple techniques to achieve detection. Besides some details lacking in the paper, I implemented the bilinear downsampling, converting to gray scale, and the edging + adaptive thresholding as described in Section 3A, 3B.1, and 3B.2.
Unfortunately, I am not getting the output this paper presents in e.g. figure 3 and 6.
The image I use for testing is as follows:
The gray scale (and downsampled) version looks fine (see the bottom of this post for the actual implementation), I used a well-known combination of the RGB components to produce it (paper does not mention how, so I took a guess).
Next is the initial edge detection using the Sobel filter outlined. This produces an image similar to the ones presented in figure 6 of the paper.
And finally, the remove the "weak edges" they apply adaptive thresholding using a 20x20 window. Here is where things go wrong.
As you can see, it does not function properly, even though I am using their stated parameter values. Additionally I have tried:
Changing the beta parameter.
Use a 2d int array instead of Bitmap objects to simplify creating the integral image.
Try a higher Gamma parameter so the initial edge detection allows more "edges".
Change the window to e.g. 10x10.
Yet none of the changes made an improvement; it keeps producing images as the one above. My question is: what am I doing different than what is outlined in the paper? and how can I get the desired output?
Code
The (cleaned) code I use:
public int[][] toGrayscale(Bitmap bmpOriginal) {
int width = bmpOriginal.getWidth();
int height = bmpOriginal.getHeight();
// color information
int A, R, G, B;
int pixel;
int[][] greys = new int[width][height];
// scan through all pixels
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
// get pixel color
pixel = bmpOriginal.getPixel(x, y);
R = Color.red(pixel);
G = Color.green(pixel);
B = Color.blue(pixel);
int gray = (int) (0.2989 * R + 0.5870 * G + 0.1140 * B);
greys[x][y] = gray;
}
}
return greys;
}
The code for edge detection:
private int[][] detectEges(int[][] detectionBitmap) {
int width = detectionBitmap.length;
int height = detectionBitmap[0].length;
int[][] edges = new int[width][height];
// Loop over all pixels in the bitmap
int c1 = 0;
int c2 = 0;
for (int y = 0; y < height; y++) {
for (int x = 2; x < width -2; x++) {
// Calculate d0 for each pixel
int p0 = detectionBitmap[x][y];
int p1 = detectionBitmap[x-1][y];
int p2 = detectionBitmap[x+1][y];
int p3 = detectionBitmap[x-2][y];
int p4 = detectionBitmap[x+2][y];
int d0 = Math.abs(p1 + p2 - 2*p0) + Math.abs(p3 + p4 - 2*p0);
if(d0 >= Gamma) {
c1++;
edges[x][y] = Gamma;
} else {
c2++;
edges[x][y] = d0;
}
}
}
return edges;
}
The code for adaptive thresholding. The SAT implementation is taken from here:
private int[][] AdaptiveThreshold(int[][] detectionBitmap) {
// Create the integral image
processSummedAreaTable(detectionBitmap);
int width = detectionBitmap.length;
int height = detectionBitmap[0].length;
int[][] binaryImage = new int[width][height];
int white = 0;
int black = 0;
int h_w = 20; // The window size
int half = h_w/2;
// Loop over all pixels in the bitmap
for (int y = half; y < height - half; y++) {
for (int x = half; x < width - half; x++) {
// Calculate d0 for each pixel
int sum = 0;
for(int k = -half; k < half - 1; k++) {
for (int j = -half; j < half - 1; j++) {
sum += detectionBitmap[x + k][y + j];
}
}
if(detectionBitmap[x][y] >= (sum / (h_w * h_w)) * Beta) {
binaryImage[x][y] = 255;
white++;
} else {
binaryImage[x][y] = 0;
black++;
}
}
}
return binaryImage;
}
/**
* Process given matrix into its summed area table (in-place)
* O(MN) time, O(1) space
* #param matrix source matrix
*/
private void processSummedAreaTable(int[][] matrix) {
int rowSize = matrix.length;
int colSize = matrix[0].length;
for (int i=0; i<rowSize; i++) {
for (int j=0; j<colSize; j++) {
matrix[i][j] = getVal(i, j, matrix);
}
}
}
/**
* Helper method for processSummedAreaTable
* #param row current row number
* #param col current column number
* #param matrix source matrix
* #return sub-matrix sum
*/
private int getVal (int row, int col, int[][] matrix) {
int leftSum; // sub matrix sum of left matrix
int topSum; // sub matrix sum of top matrix
int topLeftSum; // sub matrix sum of top left matrix
int curr = matrix[row][col]; // current cell value
/* top left value is itself */
if (row == 0 && col == 0) {
return curr;
}
/* top row */
else if (row == 0) {
leftSum = matrix[row][col - 1];
return curr + leftSum;
}
/* left-most column */
if (col == 0) {
topSum = matrix[row - 1][col];
return curr + topSum;
}
else {
leftSum = matrix[row][col - 1];
topSum = matrix[row - 1][col];
topLeftSum = matrix[row - 1][col - 1]; // overlap between leftSum and topSum
return curr + leftSum + topSum - topLeftSum;
}
}
Marvin provides an approach to find text regions. Perhaps it can be a start point for you:
Find Text Regions in Images:
http://marvinproject.sourceforge.net/en/examples/findTextRegions.html
This approach was also used in this question:
How do I separates text region from image in java
Using your image I got this output:
Source Code:
package textRegions;
import static marvin.MarvinPluginCollection.findTextRegions;
import java.awt.Color;
import java.util.List;
import marvin.image.MarvinImage;
import marvin.image.MarvinSegment;
import marvin.io.MarvinImageIO;
public class FindVehiclePlate {
public FindVehiclePlate() {
MarvinImage image = MarvinImageIO.loadImage("./res/vehicle.jpg");
image = findText(image, 30, 20, 100, 170);
MarvinImageIO.saveImage(image, "./res/vehicle_out.png");
}
public MarvinImage findText(MarvinImage image, int maxWhiteSpace, int maxFontLineWidth, int minTextWidth, int grayScaleThreshold){
List<MarvinSegment> segments = findTextRegions(image, maxWhiteSpace, maxFontLineWidth, minTextWidth, grayScaleThreshold);
for(MarvinSegment s:segments){
if(s.height >= 10){
s.y1-=20;
s.y2+=20;
image.drawRect(s.x1, s.y1, s.x2-s.x1, s.y2-s.y1, Color.red);
image.drawRect(s.x1+1, s.y1+1, (s.x2-s.x1)-2, (s.y2-s.y1)-2, Color.red);
image.drawRect(s.x1+2, s.y1+2, (s.x2-s.x1)-4, (s.y2-s.y1)-4, Color.red);
}
}
return image;
}
public static void main(String[] args) {
new FindVehiclePlate();
}
}

Random 2D Cityscape generator, how do I randomly generate?

I have to randomly generate a cityscape with 3 layered functions in processing. I'm doing so by drawing each floor in a loop that runs until a random integer, and doing the same thing with floors per building. Currently, the floors are initially randomly generated, but then they eventually fill out to the maximum of the random function. How do I get it so they stay random? Thanks, code is below.
int boxX = 0;
int boxY = 479;
void setup() {
size(1000, 500);
background(255);
frameRate(10);
}
void draw() {
for (int i = 0; i < 8; i++) {
building(boxX, boxY);
translate(150, 0);
}
}
void room(int boxX, int boxY) {
rect(boxX, boxY, 20, 20);
}
void floor(int boxX, int boxY) {
int randomNum = (int)random(3, 5);
for (int i=0; i<= randomNum; i++) {
room(boxX, boxY);
boxX += 20;
}
}
void building(int boxX, int boxY) {
int randomNum = int(random(10, 20));
for (int i = 0; i < randomNum; i++) {
floor(boxX, boxY);
boxY -= 20;
}
}
The problem is that you're generating a random cityscape every single frame, but you're never clearing out old frames. That means that your new frames are just drawn right on top of your old frames.
To better see what I'm talking about, clear out the old frames by adding a call to background() as the first line in your draw() function:
void draw() {
background(200);
for (int i = 0; i < 8; i++) {
building(boxX, boxY);
translate(150, 0);
}
}
You need to take a step back and ask yourself exactly what you want to happen. Do you want to generate a new cityscape every frame? If so leave the call to background() in. Do you just want to generate a single cityscape? If so then call noLoop() to prevent the draw() function from being called more than once, or store your cityscape in a data structure that you redraw every frame instead of regenerating.

Processing in Java - drawn clearing rectangle breaks after calling a method

I am using Processing in Java to perpetually draw a line graph. This requires a clearing rectangle to draw over drawn lines to make room for the new part of the graph. Everything works fine, but when I call a method, the clearing stops working as it did before. Basically the clearing works by drawing a rectangle in front of where the line is currently at
Below are the two main methods involved. The drawGraph function works fine until I call the redrawGraph which redraws the graph based on the zoom. I think the center variable is the cause of the problem but I cannot figure out why.
public void drawGraph()
{
checkZoom();
int currentValue = seismograph.getCurrentValue();
int lastValue = seismograph.getLastValue();
step = step + zoom;
if(step>offset){
if(restartDraw == true)
{
drawOnGraphics(step-zoom, lastY2, step, currentValue);
image(graphGraphics, 0, 0);
restartDraw = false;
}else{
drawOnGraphics(step-zoom, lastValue, step, currentValue);
image(graphGraphics, 0, 0);
}
} // draw graph (connect last to current point // increase step - x axis
float xClear = step+10; // being clearing area in front of current graph
if (xClear>width - 231) {
xClear = offset - 10; // adjust for far side of the screen
}
graphGraphics.beginDraw();
if (step>graphSizeX+offset) { // draw two clearing rectangles when graph isn't split
// left = bg.get(0, 0, Math.round(step-graphSizeX), height - 200); // capture clearing rectangle from the left side of the background image
// graphGraphics.image(left, 0, 0); // print left clearing rectangle
// if (step+10<width) {
// right = bg.get(Math.round(step+10), 0, width, height - 200); // capture clearing rectangle from the right side of the background image
// // print right clearing rectangle
// }
} else { // draw one clearing rectangle when graph is split
center = bg.get(Math.round(xClear), lastY2, offset, height - 200); // capture clearing rectangle from the center of the background image
graphGraphics.image(center, xClear - 5, 0);// print center clearing rectangle
}
if (step > graphSizeX+offset) { // reset set when graph reaches the end
step = 0+offset;
}
graphGraphics.endDraw();
image(graphGraphics, 0 , 0);
System.out.println("step: " + step + " zoom: " + zoom + " currentValue: "+ currentValue + " lastValue: " + lastValue);
}
private void redrawGraph() //resizes graph when zooming
{
checkZoom();
Object[] data = seismograph.theData.toArray();
clearGraph();
step = offset;
int y2, y1 = 0;
int zoomSize = (int)((width - offset) / zoom);
int tempCount = 0;
graphGraphics.beginDraw();
graphGraphics.strokeWeight(2); // line thickness
graphGraphics.stroke(242,100,66);
graphGraphics.smooth();
while(tempCount < data.length)
{
try
{
y2 = (int)data[tempCount];
step = step + zoom;
if(step > offset && y1 > 0 && step < graphSizeX+offset){
graphGraphics.line(step-zoom, y1, step, y2);
}
y1 = y2;
tempCount++;
lastY2 = y2;
}
catch (Exception e)
{
System.out.println(e.toString());
}
}
graphGraphics.endDraw();
image(graphGraphics, 0, 0);
restartDraw = true;
}
Any help and criticisms are welcome. Thank you for your valuable time.
I'm not sure if that approach is the best. You can try something as simple as this:
// Learning Processing
// Daniel Shiffman
// http://www.learningprocessing.com
// Example: a graph of random numbers
float[] vals;
void setup() {
size(400,200);
smooth();
// An array of random values
vals = new float[width];
for (int i = 0; i < vals.length; i++) {
vals[i] = random(height);
}
}
void draw() {
background(255);
// Draw lines connecting all points
for (int i = 0; i < vals.length-1; i++) {
stroke(0);
strokeWeight(2);
line(i,vals[i],i+1,vals[i+1]);
}
// Slide everything down in the array
for (int i = 0; i < vals.length-1; i++) {
vals[i] = vals[i+1];
}
// Add a new random value
vals[vals.length-1] = random(height);//use seismograph.getCurrentValue(); here instead
}
You can easily do the same using a PGraphics buffer as your code suggests:
// Learning Processing
// Daniel Shiffman
// http://www.learningprocessing.com
// Example: a graph of random numbers
float[] vals;
PGraphics graph;
void setup() {
size(400,200);
graph = createGraphics(width,height);
// An array of random values
vals = new float[width];
for (int i = 0; i < vals.length; i++) {
vals[i] = random(height);
}
}
void draw() {
graph.beginDraw();
graph.background(255);
// Draw lines connecting all points
for (int i = 0; i < vals.length-1; i++) {
graph.stroke(0);
graph.strokeWeight(2);
graph.line(i,vals[i],i+1,vals[i+1]);
}
graph.endDraw();
image(graph,0,0);
// Slide everything down in the array
for (int i = 0; i < vals.length-1; i++) {
vals[i] = vals[i+1];
}
// Add a new random value
vals[vals.length-1] = random(height);//use seismograph.getCurrentValue(); here instead
}
The main idea is to cycle the newest data in an array and simply draw the values from this shifting array. As long as you clear the previous frame (background()) the graph should look ok.

Categories

Resources