Ch 10 – Image Processing
Supanit Angsirikul
Processing image with
Draw on Image
size(200, 200);
PImage im = loadImage(“data/android1.png");
im.resize(width, height);
image(im, 0, 0);
// draw a circle
fill(255, 0, 0, 150);
noStroke();
ellipse(width/2, height/2 + 10, 30, 30);
save("test.png");
Scale Image (icon or thumbnail)
PImage android = loadImage(“data/android1.png");
android.resize(50, 50); // resize() Enlarge or reduce the image size
android.save("test.png");
Add Image on Image
size(200, 200);
PImage android = loadImage(“data/android1.png");
PImage blue = loadImage(“data/blue.png");
android.resize(width, height);
image(android, 0, 0); //Draw an image on the sketch canvas
image(blue, 150, 10);
Create and Copy
Create and Copy
size(600, 200);
// 1. Original
PImage im1 = loadImage("data/android2.jpg");
image(im1, 0, 0);
// 2. Copy from original
PImage im2 = createImage(im1.width, im1.height, RGB);
im2.copy(im1, 0, 0, im1.width/2, im1.height/2,
0, 0, im1.width, im1.height);
image(im2, 200, 0);
// 3. Copy to itself
im1.copy(50, 0, 50, 50, 0, 0, 100, 100);
image(im1, 400, 0);
Get Pixel and Image On Screen
size(200, 200);
background(255);
noStroke();
fill(0, 255, 0);
ellipse(width/2, height/2, 100, 100);
/* Get pixel on Screen
get(x, y) get a pixel at x,y
*/
color c = get(width/2, height/2);
println(red(c) + ", " + green(c) + ", " + blue(c));
/* Get image on Screen
get(x, y, w, h) get image at x,y with size w. h.
get() get image of the screen
*/
PImage im = get(width/2, height/2, 50, 50);
image(im, 0, 0);
Set Pixel On Screen
/* Set pixel On Screen
set(x, y, color) set a pixel(color) at x, y
*/
size(255, 255);
for (int i = 0; i < width; i++)
for (int j = 0; j < height; j++)
set(i, j, color(0, i, j));
Set Image On Screen
/* Set image On Screen
set(x, y, img) set image at x, y
*/
size(400, 400);
PImage im = loadImage(“data/android1.png");
set(200, 200, im);
// image(im, 200, 200);
Get and Set on Image
/* Get and Set on Image
image.get(x, y, w, h)
image.get()
image.set(x, y, img)
*/
size(250, 250);
PImage android = loadImage("data/android2.jpg");
android.resize(width, height);
PImage red = loadImage("data/red.png");
PImage redx = red.get(0, 0, 38, 58);
android.set(10, 0, redx);
image(android, 0, 0);
Load and Update Pixels
Load and Update Pixels
size(255, 255);
loadPixels();
for (int g = 0; g < height; g++)
for (int r = 0; r < width; r++)
pixels[g*width + r] = color(r, g, 0);
updatePixels();
Load and Update Pixels
size(255, 255);
loadPixels();
for (int y = 30; y < height-30; y++)
for (int x = 60; x < width-60; x++)
pixels[y*width + x] = color(0,0,0);
updatePixels();
Load and Update Pixels
size(200, 200);
int cx = width/2;
int cy = height/2;
int rsq1 = 50*50;
int rsq2 = 51 * 51;
loadPixels();
for(int x = -cx; x < cx; x++)
for(int y = -cy; y < cy; y++)
if (x*x + y*y > rsq1 && x*x + y*y < rsq2)
pixels[(y + cy)*width + (x+cx)] = color(0,0,0);
updatePixels();
To Manipulate pixels in image:
1. We can load image and show on the screen then create pixels[] from the screen.
2. We can create pixels[] from the image directly by
<p-image>.loadPixels()
and then
<p-image>.updatePixels()
to copy back to the image.
Manipulate pixels in image
size(200, 200);
PImage im = loadImage(“data/android2.jpg");
im.resize(width, height);
im.loadPixels();
for (int x = 50; x < 150; x++)
im.pixels[x*width + x] = color(255,0,0);
im.updatePixels();
image(im, 0, 0);
Few Lines Blur - To blur a picture. We can insert a white line in every few lines.
void setup() {
size(400, 400);
noLoop();
}
int step = 3;
void draw() {
PImage im = loadImage(“data/android2.jpg");
im.resize(width, height);
im.loadPixels();
for (int i = 0; i < im.pixels.length; i+=step)
im.pixels[i] = color(255, 255, 255);
im.updatePixels();
image(im, 0, 0);
}
void keyPressed() {
if (key == 'a')
++step;
else if (key == 'z')
--step;
println(step);
redraw();
}
Color Modification - Pixel colors can be modified unrelated to their locations.
size(400, 400);
background(190, 250, 0);
PImage im = loadImage("data/android2.jpg");
im.resize(width, height);
im.loadPixels();
for (int i = 0; i < im.pixels.length; i++) {
color c = im.pixels[i];
float r = red(c); //Retrieve the red value
float g = green(c); //Retrieve the green value
float b = blue(c); //Retrieve the blue value
im.pixels[i] = color(r, 0, b); // remove green
// im.pixels[i] = color(b, g, r); // red <-> blue
// im.pixels[i] = color(g, r, b); // red <-> green
// im.pixels[i] = color(r, b, g); // green <-> blue
// im.pixels[i] = color(r, g, b, 170); // alpha 170
// im.pixels[i] = color(r, g, b, (255 - i % im.width * 0.5));
}
im.updatePixels();
image(im, 0, 0);
Turning background to transparency
int threshold = 730;
size(800, 400);
PImage im1 = loadImage(“data/android2.jpg");
im1.resize(width/2, height);
background(190, 250, 0); // light green background
image(im1, 0, 0);
// create an image that supports alpha.
PImage im2 = createImage(im1.width, im1.height, ARGB);
im1.loadPixels();
im2.loadPixels();
for (int i = 0; i < im1.pixels.length; i++) {
float r = red(im1.pixels[i]);
float g = green(im1.pixels[i]);
float b = blue(im1.pixels[i]);
if ((r + g + b) > threshold)
im2.pixels[i] = color(r, g, b, 0);
else
im2.pixels[i] = color(r, g, b, 255);
}
im2.updatePixels();
// im2.save("/data/tranAndroid.png");
image(im2, im1.width, 0);
Negative, Grayscale, Sepia
void setup() {
size(1000, 800);
PImage im = loadImage(“data/p1.jpg");
im.resize(width/2, height/2);
image(im, 0, 0);
negative();
gray();
sepia();
}
void negative() {
PImage im = loadImage(“data/p1.jpg");
im.resize(width/2, height/2);
im.loadPixels();
for (int i = 0; i < im.pixels.length; i++) {
color c = im.pixels[i];
im.pixels[i] = color(255-red(c), 255-green(c), 255-blue(c));
}
im.updatePixels();
image(im, width/2, 0);
}
void gray() {
PImage im = loadImage(“data/p1.jpg");
im.resize(width/2, height/2);
im.loadPixels();
for (int i = 0; i < im.pixels.length; i++) {
color c = im.pixels[i];
im.pixels[i] = color(red(c)*0.3 + green(c)*0.59 + blue(c)*0.11);
}
im.updatePixels();
image(im, 0, height/2);
}
void sepia() {
PImage im = loadImage(“data/p1.jpg");
im.resize(width/2, height/2);
im.loadPixels();
for (int i = 0; i < im.pixels.length; i++)
im.pixels[i] = sepia(im.pixels[i]);
im.updatePixels();
image(im, width/2, height/2);
}
// Sepia tones is a warmer coloring that is used in archiving grayscale photos.
color sepia(color c) {
float r = red(c)*0.393 + green(c)*0.769 + blue(c)*0.189;
float g = red(c)*0.349 + green(c)*0.686 + blue(c)*0.168;
float b = red(c)*0.272 + green(c)*0.534 + blue(c)*0.131;
return color(r, g, b);
}
Negative, Grayscale, Sepia
Custom Tone
int r = 255;
int g = 240; // change green value to 220 for a red-toned sepia palette
int b = 192;
color[] palette = new color[256];
void setupPalette() {
for (int i = 0; i < palette.length; i++) {
palette[i] = color(r*i/255, g*i/255, b*i/255);
}
}
color custom(color c) {
float gray = red(c)*0.3 + green(c)*0.59 + blue(c)*0.11;
return palette[int(gray)];
}
void setup() {
size(1000, 800);
setupPalette();
noLoop();
}
void draw() {
PImage im = loadImage(“data/p1.jpg");
im.resize(width, height);
im.loadPixels();
for (int i = 0; i < im.pixels.length; i++)
im.pixels[i] = custom(im.pixels[i]);
im.updatePixels();
image(im, 0, 0);
}
void keyPressed() {
if (key == 'a')
r += 10;
else if (key == 's')
g += 10;
else if (key == 'd')
b += 10;
else if (key == 'z')
r -= 10;
else if (key == 'x')
g -= 10;
else if (key == 'c')
b -= 10;
println(r + "," + g + "," + b);
setupPalette();
redraw();
}
Custom Tone
Pixelation Effect (to create a raster image look)
int row = 100, column = 100;
void setup() {
size(1000, 800);
noLoop();
}
void draw() {
PImage im = loadImage(“data/p6.jpg");
im.resize(width, height);
int dx = width/column;
int dy = height/row;
for (int y = 0; y < height; y += dy)
for (int x = 0; x < width; x += dx) {
fill(im.get(x, y));
rect(x, y, dx, dy);
}
}
void keyPressed() {
if (key == 'a')
row += 2;
else if (key == 'z')
row -= 2;
else if (key == 's')
column += 2;
else if (key == 'x')
column -= 2;
println(row + "," + column);
redraw();
}
Pointillism: To create paint effect.
float pointSize = 7;
int pointNumber = 15000;
void setup() {
size(1000, 800);
noStroke();
noLoop();
}
void draw() {
PImage im = loadImage(“data/road.png");
im.resize(width, height);
image(im, 0, 0);
for (int i = 0; i < pointNumber; i++) {
int x = (int)random(width);
int y = (int)random(height);
color c = get(x, y);
fill(c);
ellipse(x, y, pointSize, pointSize);
}
}
void keyPressed() {
if (key == 'a')
pointSize++;
else if (key == 'z')
pointSize--;
else if (key == 's')
pointNumber += 10;
else if (key == 'x')
pointNumber -= 10;
println(pointSize + "," + pointNumber);
redraw();
}
Copying Neighbors: to create Paint Brush effects.
int round = 3;
void setup() {
size(1000, 800);
noLoop();
}
void draw() {
PImage im = loadImage(“data/pic1.jpg");
im.resize(width, height);
image(im, 0, 0);
for (int r = 0; r < round; r++) {
for (int x = 1; x < width-1; x++)
for (int y = 1; y < height-1; y++)
set(x, y, get(int(random(x-1, x+2)), int(random(y-1, y+2))));
}
}
void keyPressed() {
if (key == 'a')
round++;
else if (key == 'z')
round--;
println(round);
redraw();
}
Displacement: to create Paint Brush effects.
int size = 1;
void setup() {
size(1000, 800);
noLoop();
noStroke();
}
void draw() {
PImage im = loadImage(“data/pic1.jpg");
im.resize(width, height);
image(im, 0, 0);
for (int x = 2; x < width; x++)
for (int y = 2; y < height; y++) {
int xx = x + int(random(-size, size));
int yy = y + int(random(-size, size));
fill(get(x, y));
rect(xx-size-1, yy-size-1, size, size);
}
}
void keyPressed() {
if (key == 'a')
size++;
else if (key == 'z')
size--;
println(size);
redraw();
}
Edge Detection and Noise Filter
int threshold = 5;
boolean rmNoise = false;
void setup() {
size(400, 400);
noLoop();
}
void draw() {
PImage im = loadImage(“data/android2.jpg");
im.resize(width, height);
image(im, 0, 0);
edgeDetect();
if (rmNoise)
removeNoise();
}
void edgeDetect() {
for (int y = 0; y < height - 1; y++)
for (int x = 0; x < width - 1; x++) {
float a = red(get(x, y));
float b = red(get(x+1, y));
if (abs(a - b) > threshold)
set(x, y, color(0));
else
set(x, y, color(255));
}
}
void removeNoise() {
for (int y = 0; y < height - 1; y++)
for (int x = 0; x < width - 1; x++) {
float a = red(get(x, y));
float b = red(get(x+1, y));
float c = red(get(x-1, y));
float d = red(get(x, y-1));
float e = red(get(x, y+1));
if ((abs(a - b) > threshold) && (abs(a - c) > threshold) ||
(abs(a - d) > threshold) && (abs(a - e) > threshold))
set(x, y, color(255));
}
}
void keyPressed() {
if (key == 'a')
threshold++;
else if (key == 'z')
threshold--;
else if (key == 's')
rmNoise = !rmNoise;
println(threshold + "," + rmNoise);
redraw();
}
Edge Detection and Noise Filter
Neighbors Edge Detection
int xd[] = { 0, 1, 1, 1, 0, -1, -1, -1, 0 };
int yd[] = { 1, 1, 0, -1, -1, -1, 0, 1, 1 };
size(1000, 800);
PImage im = loadImage(“data/pic1.jpg");
im.resize(width, height);
image(im, 0, 0);
int m[][] = new int[width][height];
for (int x = 1; x < width-1; x++)
for (int y = 1; y < height-1; y++) {
int a = 0, b = 0;
for(int i = 0; i < 8; i++) {
float b1 = brightness(get(x+xd[i], y+yd[i]));
float b2 = brightness(get(x+xd[i+1], y+yd[i+1]));
if (b1 < 128)
b++;
if (b1 < 128 && b2 > 128)
a++;
}
if ((b >= 2 && b <= 6) || a == 1)
m[x][y] = 1;
else
m[x][y] = 0;
}
for (int x = 1; x < width-1; x++)
for (int y = 1; y < height-1; y++) {
if (m[x][y] == 1)
set(x, y, color(0));
else
set(x, y, color(255));
}
Flickering
Flickering
PImage im;
float x = 0, cy = 130, r = 250;
void setup() {
size(1000, 800);
im = loadImage(“data/road.png");
im.resize(width, height);
noStroke();
}
void draw() {
image(im, 0, 0);
fill(255, 0, 0);
ellipse(++x, cy, r, r);
if (x > width)
noLoop();
}
Off-Screen Drawing
createGraphics(w, h)
Off-Screen Drawing
PImage im;
PGraphics pg;
float x = 0, cy = 130, r = 250;
void setup() {
size(1000, 800);
im = loadImage(“data/road.png");
im.resize(width, height);
pg = createGraphics(width, height);
}
void draw() {
pg.beginDraw();
pg.image(im, 0, 0);
pg.fill(255, 0, 0);
pg.noStroke();
pg.ellipse(++x, cy, r, r);
pg.endDraw();
image(pg, 0, 0);
if (x > width)
noLoop();
}
without PGraphics
void setup() {
size(900, 700);
smooth();
stroke(255);
}
void draw() {
background(0);
for (int i = 0; i < 2000; i++)
line(mouseX, mouseY, random(width), random(height));
}
with PGraphics
PGraphics pg;
void setup() {
size(900, 700);
pg = createGraphics(width, height);
}
void draw() {
pg.beginDraw();
pg.background(0);
pg.stroke(255);
pg.smooth();
for (int i = 0; i < 2000; i++)
pg.line(mouseX, mouseY, random(width), random(height));
pg.endDraw();
image(pg, 0, 0);
}
Steganography : Encoding Signature in Picture
int signature = 123;
int signaturePos = 12345;
color cover;
PImage im;
void setup() {
size(600, 400);
im = loadImage("data/pic1s.jpg");
im.resize(width, height);
image(im, 0, 0);
}
void draw() {
}
void keyPressed() {
if (key == 'e') {
im.loadPixels();
cover = im.pixels[signaturePos];
im.pixels[signaturePos] ^= signature; //^ bitwise exclusieve OR
im.updatePixels();
image(im, 0, 0);
save("data/encoded.png");
println("Encode Ok.");
}
if (key == 'd') {
im = loadImage("data/encoded.png");
im.loadPixels();
color c = im.pixels[signaturePos];
println(c ^ cover);
}
}
Steganography : Encoding Signature in Picture
Masking Lower Bits - To conceal a picture (secret) in a picture (cover)
PImage cover; // To hold unencoded cover picture
PImage secret; // To hold image to be encoded into the cover, must be the same size
int clearSecretMask = 0xFF0F0F0F; // & with color to remove rightmost 4 bits from all R/G/B channels
int clearCoverMask = 0x000F0F0F;
void setup() {
size(1200, 800);
cover = loadImage(“data/pic2s.jpg");
secret = loadImage(“data/pic6s.jpg");
cover.resize(600, 400); // Size the sketch to be the same size as the cover
secret.resize(600, 400);
image(cover, 0, 0);
image(secret, 600, 0);
}
Masking Lower Bits - To conceal a picture (secret) in a picture (cover) (ต่อ)
void draw() { }
void keyPressed() {
if (key == 'e') {
cover.loadPixels(); // Load pixels for the cover picture
secret.loadPixels(); // Load pixels for the image to be encoded
for (int i = 0; i < cover.pixels.length; i++) {
color cp = cover.pixels[i];
color sp = secret.pixels[i]; //strip off the alpha and the least significant 4 bits of R, G and B
sp = sp & ~ clearSecretMask; // right shift so that the most significant 4 bits
sp = sp >> 4; // Strip off least significant 4 bits of R, G, B from cover image
cp = cp & ~clearCoverMask; // Add the significant bits from the secret image to the cover's least significant bits
cp = cp | sp; // Replace the encoded pixel back
cover.pixels[i] = cp;
}
cover.updatePixels();
image(cover, 0, 400);
}
Masking Lower Bits - To conceal a picture (secret) in a picture (cover) (cont.)
if (key == 'd') {
int clearMask = 0x00F0F0F0;
cover.loadPixels();
for (int i = 0; i < cover.pixels.length; i++) {
color c = cover.pixels[i];
c = c & ~clearMask; // left shift and move the least significant 4 bits into the leftmost position
c = c << 4; // Replace the decoded pixel back into the picture
cover.pixels[i] = c;
}
cover.updatePixels();
image(cover, 600, 400);
}
}