reading and writing an image simultaneously Processing - image

I'm generating probability tables for one color appearing to the right of another. I have accomplished all of this. I store the tables in objects which are created for each color value. My problem is, that when I generate a new image, I'd like to create pixel 0, then make a weighted random decision for the color that will appear to the right. I think my problem is that I'm trying to read data from image I'm constructing, and write to it in the same loop. I'm not sure how processing deals with this, and I seem to be getting strange errors, often, many of my pixels are black. I believe all of my problems are occurring the third time I loop through all of the pixels (lines 60-78), and try to write pixels to the new image.
you can see in the output of println statement the colors that should be written to the new image.
Is there something I'm missing?
This is the first time I've used classes and objects to code, so please forgive any clunkiness.
Thanks in advance for any help anyone can offer.
PImage src;
PImage dstn;
HashMap library;
int counter;
color d = (0);
color seed = (0);
color ds = (0);
void setup() {
library = new HashMap<Integer, Object>();
size(200, 200);
src = loadImage("sunflower.jpg");
dstn = createImage(src.width, src.height, RGB);
src.loadPixels();
int acc = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int loc = x + y*width;
color d = src.get(x,y); // get pixel color at desired location
if (library.containsKey(d)) {
// Get the AColor object and increase the count
// We access objects from the library via its key, the String
AColor c = (AColor) library.get(d);
c.count(); // touch the counter everytime the a color is read
c.the_color(d); // add the color to the object
//c.output();
} else {
// Otherwise make a new entry in library
AColor c = new AColor(d);
// And add to the library
// put() takes two arguments, "key" and "value"
// The key for us is the String and the value is the AColor object
library.put(d, c);
} // all colors are in library now
AColor c = (AColor) library.get(d);
if (x < width - 1 ) { //If statement to ensure null pixles are not added to transition matrix
color z = src.get(x+1,y);
c.access_matrix_right(z);
} else { // this is a nasty shortcut that wraps the probability of the rightmost pixel to the leftmost pixel
color z = src.get(x,y);
c.access_matrix_right(z);
}
}
}
}
void draw() {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
color d = src.get(x,y);
AColor c = (AColor) library.get(d);
c.sort_matrix(); // add and construct all of the ArrayLists for each object
println("first loop");
}
}
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int loc1 = ((x + y*width));
color seed = src.get(x,y);
dstn.pixels[0] = seed;
color ds = src.get(x,y); // copy pixel 0 from src to dstn image
AColor c = (AColor) library.get(ds);
float chance;
int acc = 0;
chance = random(1);
float probAccum = (c.probs.get(acc));
while (chance > probAccum) {
acc++;
probAccum = probAccum + (c.probs.get(acc));
int colorToTheRight = c.colors.get(acc);
dstn.pixels[loc1] = colorToTheRight; // <-If I put this outside of the while lopp, the image is more or less normal looking.
}
println(acc + " " + c.colors.get(acc) + " , " + c.colors + " - " + c.probs + " Chance = " + chance +" -color should be" + (c.colors.get(acc)));
dstn.updatePixels();
}
}
dstn.updatePixels();
image(dstn,0,0);
noLoop();
}
class AColor {
float count;
int theColor;
int colorRight;
int acc = 0;
int z;
HashMap<Object, Integer> matrix = new HashMap<Object, Integer>();
ArrayList<Float> probs;
ArrayList<Integer> colors = new ArrayList<Integer>(); //an ArrayList is used here. Perhaps it would be better to use an Array and iterate over the hashmap to set the length
AColor(int theColorTemp) {
theColor = theColorTemp;
count = 1;
}
void the_color(int theColorTemp) {
theColor = theColorTemp;
}
void count() {
count++;
}
void access_matrix_right(int colorRightTemp) {
colorRight = colorRightTemp;
if (matrix.containsKey(colorRight)) { // if library has entry for current pixel
int val = ((Integer) matrix.get(colorRight)).intValue(); //accumulator
matrix.put(colorRight, new Integer(val + 1)); // add 1 to
}
else {
matrix.put(colorRight,1); //adds entry & a value of 1 if entry does not exist
colors.add(colorRight);
}
}
void sort_matrix() {
probs = new ArrayList<Float>();
for (int i = 0; i <= colors.size()-1; i++) { //for number elements in list
probs.add((matrix.get(colors.get(i))) / count); // add element in array probs (number of occurrances of a color on the right/ total pixels on right )
}
}
}

Why not read all your pixels into a second image write to that, then write that back to the original one?
wouldn't something like this work? (untested)
int numPixelsX = 500;
int numPixelsY = 500;
PImage captureImage = createImage (numPixelsX,numPixelsY, ARGB);
void setup(){
size(500,500);
}
void draw(){
captureImage.loadPixels();
captureImage = pushPixels(captureImage);
captureImage.updatePixels();
image(captureImage, 0, 0);
}
PImage pushPixels(PImage readImage){
PImage writeImage = createImage(numPixelsX,numPixelsY,ARGB);
writeImage.loadPixels();
writeImage = readImage();
//do your stuff here from the read image to the write image
writeImage.updatePixels();
return writeImage;
}

Related

How can I make a grid of tiles (that can be rotated randomly) in processing?

I have the following code in Processing that will produce a grid of randomly selected tiles from loaded files:
static int img_count = 6;
PImage[] img;
void setup() {
size(1200, 800);
img = new PImage[img_count];
for (int i = 0; i < img_count; i++) {
img[i] = loadImage("./1x/Artboard " + (i+1) + ".png");
}
}
void draw() {
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 12; j++) {
int rand_index = int(random(img_count));
image(img[rand_index], 100 * i, 100 * j, 100, 100 );
}
}
}
By itself, it almost does what I want:
But I need that every tile be randomly rotated as well, so I tried this:
void draw() {
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 12; j++) {
float r = int(random(4)) * HALF_PI; // I added this
rotate(r); // I added this
int rand_index= int(random(img_count));
image(img[rand_index], 100 * i, 100 * j, 100, 100 );
}
}
}
This second code doesn't act as I intended, as rotate() will rotate the entire image, including tiles that were already rendered. I couldn't find an appropriate way to rotate a tile the way I want, is there any way to rotate the tile before placing it?
You will probably need to translate before rotating.
The order of transformations is important (e.g. translating, then rotating will be a different location than rotation, then translating).
In your case image(img, x, y) makes it easy to miss that behind the scenes it's more like translate(x,y);image(img, 0, 0);.
I recommend:
void draw() {
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 12; j++) {
float r = int(random(4)) * HALF_PI; // I added this
translate(100 * i, 100 * j); // translate first
rotate(r); // I added this
int rand_index= int(random(img_count));
image(img[rand_index], 0, 0, 100, 100 );
}
}
}
(depending on your setup, you might find imageMode(CENTER); (in setup()) handy to rotate from image centre (as opposed to top left corner (default)))

KinectV2 - Getting a boundary around the body

I am trying to draw a rectangle around the body using its upper left corner and bottom right corner detected by Kinect.
The left most and the highest points are detected but I have difficulty finding the right most and the lowest point. The current right mark is jumping up and down and does not move in x-direction.
import org.openkinect.processing.*;
Kinect2 kinect2;
float minThresh = 420;
float maxThresh = 1500;
PImage img;
void setup() {
size(512, 424);
kinect2 = new Kinect2(this);
kinect2.initDepth();
kinect2.initDevice();
img = createImage(kinect2.depthWidth, kinect2.depthHeight, RGB);
}
void draw() {
background(0);
img.loadPixels();
PImage dImg = kinect2.getDepthImage();
int[] depth = kinect2.getRawDepth();
// left side
int leftRecord = kinect2.depthWidth;
int lx = 0;
int ly = 0;
// right side
int rightRecord = 0;
int rx =0;
int ry = 0;
for (int x = 0; x < kinect2.depthWidth; x++) {
for (int y = 0; y < kinect2.depthHeight; y++) {
int offset = x + y*kinect2.depthWidth;
// Grabbing the raw depth
int d = depth[offset];
// Testing against threshold
if (d > minThresh && d < maxThresh && x>50) {
img.pixels[offset] = color(255, 0, 150);
//finding the left most point
if (x < leftRecord) {
leftRecord = x;
lx = x;
ly = y;
}
// finding the right most point
// THE BIT THAT DOES NOT WORK
if( x > rightRecord && x < kinect2.depthWidth){
rightRecord = x;
rx = x;
ry = y;
}
} else {
img.pixels[offset] = dImg.pixels[offset];
}
}
}
img.updatePixels();
image(img, 0, 0);
fill(150, 0, 255);
ellipse(lx,ly,30,30);
ellipse(rx,ry,30,30);
}

Random() happening only once

I have this for() loop where I am randomizing the selection of slices of a picture, to display 16 slices of an image in a random order.
I'm picking those slices from an array and I have a variable that picks up what slice is going to be selected in the array.
The problem being that I'd think that the random function would be triggered for every frame, but it's triggered only once.
Here's the code :
void setup() {
size(720,720);
slices = new PImage[16];
slices[0] = loadImage("1.png");
slices[1] = loadImage("2.png");
slices[2] = loadImage("3.png");
slices[3] = loadImage("4.png");
slices[4] = loadImage("5.png");
slices[5] = loadImage("6.png");
slices[6] = loadImage("7.png");
slices[7] = loadImage("8.png");
slices[8] = loadImage("9.png");
slices[9] = loadImage("10.png");
slices[10] = loadImage("11.png");
slices[11] = loadImage("12.png");
slices[12] = loadImage("13.png");
slices[13] = loadImage("14.png");
slices[14] = loadImage("15.png");
slices[15] = loadImage("16.png");
frameRate(1);
}
void draw() {
for (int a = 0; a < 16; a++){
int rand = int(random(slices.length));
image(slices[rand],x,y,size,size);
x += size;
if (a % 4 == 3){
y += size;
x = 0;
}
}
It's dispalying the randomized slices only once and then I end up with a fix image. What I'd like to have is random slices appearing at every frame.
Thanks for your help !
You have 2 problems in your code.
First, you may not want to choose a random index.
This is because the same image could be chosen twice.
Instead, you could shuffle the array before drawing the images, like this:
for (int i = slices.length; i > 1; i--) {
//choose a random index for the i-th element to be swapped with
int j = (int)random(i);
//swap them
PImage temp = slices[j];
slices[j] = slices[i-1];
slices[i-1] = temp;
}
Second, the index is chosen on every frame, and the images are drawn, too, but you can't see it, because your code never resets y back to 0, meaning that they are below the screen.
You can fix this by adding
y = 0;
to the top or bottom of your draw().
Could it be because you've forgot to clear the screen (e.g. calling background()) (meaning once you've drawn an image it will stay rendered) ?
You could also make use of the for loop in setup to avoid repeating yourself:
int numSlices = 16;
PImage[] slices = new PImage[numSlices];
float x, y;
float size = 180;
void setup() {
size(720, 720);
for(int i = 0 ; i < numSlices; i++){
slices[i] = loadImage((i+1) + ".png");
}
frameRate(1);
}
void draw() {
background(255);
for (int a = 0; a < numSlices; a++) {
int rand = int(random(numSlices));
image(slices[rand], x, y, size, size);
x += size;
if (a % 4 == 3) {
y += size;
x = 0;
}
}
y = 0;
}
Additionally you could easily format your code (via CMD+T on OSX or Ctrl+T on Windows/Linux)
Update Kamakura (+1) correctly pointing out y not being reset to 0.
As a distraction I though't point you to IntList's shuffle() method:
int numSlices = 16;
PImage[] slices = new PImage[numSlices];
float x, y;
float size = 180;
IntList indices = new IntList();
void setup() {
size(720, 720);
for(int i = 0 ; i < numSlices; i++){
slices[i] = loadImage((i+1) + ".png");
indices.append(i);
}
frameRate(1);
}
void draw() {
background(255);
// shuffle list
indices.shuffle();
// reset y
y = 0;
for (int a = 0; a < numSlices; a++) {
int rand = indices.get(a);
image(slices[rand], x, y, size, size);
x += size;
if (a % 4 == 3) {
y += size;
x = 0;
}
}
}
Extra reason to play with it, other than a learning experience is that fact that it will be unlikely to get the same random index repeated.
Regarding splicing/shuffling, here's a modified version of the Load and Display example:
/**
* Load and Display
*
* Images can be loaded and displayed to the screen at their actual size
* or any other size.
*/
PImage img; // Declare variable "a" of type PImage
// shuffled image
PImage imgShuffled;
// list of indices to shuffle
IntList shuffleIndices = new IntList();
// configure image slicing rows/columns
int rows = 4;
int cols = 4;
// total sections
int numSections = rows * cols;
// image section dimensions
int sectionWidth;
int sectionHeight;
void setup() {
size(640, 360);
frameRate(1);
// The image file must be in the data folder of the current sketch
// to load successfully
img = loadImage("https://processing.org/examples/moonwalk.jpg"); // Load the image into the program
// calculate section dimensions
sectionWidth = img.width / cols;
sectionHeight = img.height / rows;
// allocate a separate image to copy shuffled pixels into
imgShuffled = createImage(img.width, img.height, RGB);
// populate image section indices
for(int i = 0 ; i < numSections; i++){
shuffleIndices.append(i);
}
}
void shuffleImage(){
// shuffle the list
shuffleIndices.shuffle();
// Ta-da!
println(shuffleIndices);
// loop through each section
for(int i = 0 ; i < numSections; i++){
// index to row, col conversion
int srcCol = i % cols;
int srcRow = i / cols;
// convert to pixel coordinates to copy from
int srcX = srcCol * sectionWidth;
int srcY = srcRow * sectionHeight;
// get random / shuffled index
int index = shuffleIndices.get(i);
// same row, col, to pixel conversion to copy to
int dstCol = index % cols;
int dstRow = index / cols;
int dstX = dstCol * sectionWidth;
int dstY = dstRow * sectionHeight;
// copy from original image to shuffled pixel coordinates
imgShuffled.copy(img,srcX,srcY,sectionWidth,sectionHeight,dstX,dstY,sectionWidth,sectionHeight);
}
}
void draw() {
shuffleImage();
// Displays the image at its actual size at point (0,0)
image(imgShuffled, 0, 0);
}

Image quality improvement in Opencv

I have two images. One has more green color and another one has better quality (it has right color). How can I improve the first one to have the similar color as the second one.I used the contrast enhancement as
//Contrast enhancement
for (int y = 0; y < rotated.rows; y++)
{
for (int x = 0; x < rotated.cols; x++)
{
for (int c = 0; c < 3; c++)
{
//"* Enter the alpha value [1.0-3.0]: "
//"* Enter the beta value [0-100]: ";
rotated.at<Vec3b>(y, x)[c] =
saturate_cast<uchar>(2.5*(rotated.at<Vec3b>(y, x)[c]) + 30);
}
}
}
It brightens the image. But I like to have similar color as the second one. What are the RGB values to change to have the second image's color.
For contrast enhancement you can use the equivalent of Matlab imadjust. You can find an OpenCV implementation here.
Applying imadjust with default parameters on each separate channel you get:
Here the full code:
#include <opencv2\opencv.hpp>
#include <vector>
#include <algorithm>
using namespace std;
using namespace cv;
void imadjust(const Mat1b& src, Mat1b& dst, int tol = 1, Vec2i in = Vec2i(0, 255), Vec2i out = Vec2i(0, 255))
{
// src : input CV_8UC1 image
// dst : output CV_8UC1 imge
// tol : tolerance, from 0 to 100.
// in : src image bounds
// out : dst image buonds
dst = src.clone();
tol = max(0, min(100, tol));
if (tol > 0)
{
// Compute in and out limits
// Histogram
vector<int> hist(256, 0);
for (int r = 0; r < src.rows; ++r) {
for (int c = 0; c < src.cols; ++c) {
hist[src(r, c)]++;
}
}
// Cumulative histogram
vector<int> cum = hist;
for (int i = 1; i < hist.size(); ++i) {
cum[i] = cum[i - 1] + hist[i];
}
// Compute bounds
int total = src.rows * src.cols;
int low_bound = total * tol / 100;
int upp_bound = total * (100 - tol) / 100;
in[0] = distance(cum.begin(), lower_bound(cum.begin(), cum.end(), low_bound));
in[1] = distance(cum.begin(), lower_bound(cum.begin(), cum.end(), upp_bound));
}
// Stretching
float scale = float(out[1] - out[0]) / float(in[1] - in[0]);
for (int r = 0; r < dst.rows; ++r)
{
for (int c = 0; c < dst.cols; ++c)
{
int vs = max(src(r, c) - in[0], 0);
int vd = min(int(vs * scale + 0.5f) + out[0], out[1]);
dst(r, c) = saturate_cast<uchar>(vd);
}
}
}
int main()
{
Mat3b img = imread("path_to_image");
vector<Mat1b> planes;
split(img, planes);
for (int i = 0; i < 3; ++i)
{
imadjust(planes[i], planes[i]);
}
Mat3b result;
merge(planes, result);
return 0;
}

I made a processing program that generates a mandelbrot set but don't know how to effectively implement a zoom method

I'm not sure if it is possible in processing but I would like to be able to zoom in on the fractal without it being extremely laggy and buggy. What I currently have is:
int maxIter = 100;
float zoom = 1;
float x0 = width/2;
float y0 = height/2;
void setup(){
size(500,300);
noStroke();
smooth();
}
void draw(){
translate(x0, y0);
scale(zoom);
for(float Py = 0; Py < height; Py++){
for(float Px = 0; Px < width; Px++){
// scale pixel coordinates to Mandelbrot scale
float w = width;
float h = height;
float xScaled = (Px * (3.5/w)) - 2.5;
float yScaled = (Py * (2/h)) - 1;
float x = 0;
float y = 0;
int iter = 0;
while( x*x + y*y < 2*2 && iter < maxIter){
float tempX = x*x - y*y + xScaled;
y = 2*x*y + yScaled;
x = tempX;
iter += 1;
}
// color pixels
color c;
c = pickColor(iter);
rect(Px, Py,1,1);
fill(c);
}
}
}
// pick color based on time pixel took to escape (number of iterations through loop)
color pickColor(int iters){
color b = color(0,0,0);
if(iters == maxIter) return b;
int l = 1;
color[] colors = new color[maxIter];
for(int i = 0; i < colors.length; i++){
switch(l){
case 1 : colors[i] = color(255,0,0); break;
case 2 : colors[i] = color(0,0,255); break;
case 3 : colors[i] = color(0,255,0); break;
}
if(l == 1 || l == 2) l++;
else if(l == 3) l = 1;
else l--;
}
return colors[iters];
}
// allow zooming in and out
void mouseWheel(MouseEvent event){
float direction = event.getCount();
if(direction < 0) zoom += .02;
if(direction > 0) zoom -= .02;
}
// allow dragging back and forth to change view
void mouseDragged(){
x0+= mouseX-pmouseX;
y0+= mouseY-pmouseY;
}
but it doesn't work very well. It works alright at the size and max iteration I have it set to now (but still not well) and is completely unusable at larger sizes or higher maximum iterations.
The G4P library has an example that does exactly this. Download the library and go to the G4P_MandelBrot example. The example can be found online here.
Hope this helps!

Resources