Project 09: Computational Portrait (Custom Pixel)

i used my portrait as an each pixel to create a whole portrait. I used smaller images for face & background section, but bigger and rotated images for hair and eye section to separate the section of my feature.

sketchDownload
// Alicia Kim
// yoonbink
// Section B

function preload(){ //load the image
    alicia = loadImage("https://i.imgur.com/FPEjcyO.jpeg");
}


function setup() {
    createCanvas(480, 480);
    imageMode(CENTER);
    angleMode(DEGREES);
    background(220);
    alicia.resize(480,480); //resize alicia to canvas size
    alicia.loadPixels(); //load pixels
}

function draw() {
    var x = floor(random(alicia.width)); //random x-coordinate value
    var y = floor(random(alicia.height)); //random y-coordinate value
    var pixColor = alicia.get(x,y); //get random coordinate in the canvas
    tint(pixColor); //tint with the color of that coordinate 

// divide sections by hair and the rest

    if (pixColor[0]>130) { //face & background has smaller images
        image(alicia,x,y,9,9);
    }

    if (pixColor[0]<130) { //hair section has bigger & rotated images 
        push();
        translate(x,y);
        rotate(180);
        image(alicia,0,0,13,13);
        pop();   
    }
}

Looking Outwards 09: A Focus on Women and Non-binary Practitioners in Computational Art

Sinew Flex is a responsive installation by architect Jenny Sabin. Jenny Sabin is an architect using a computational techniques to create experimental form, bringing new perspectives to ways we see structures around us. She studied interdisciplinary visual art for bachelors and architecture for masters degree. Since she specializes in adaptive architecture, material computation, and biomimicry,  most of her works contain bioinspired design created through knitting of responsive fibres. Similarly, Sinew Flex, a 2 story double canopy structure connected with a central bifurcated tubular form, is mathematically generated and activated by digital knitting process and light.The responsive fibres used in the structure change color and glow in response to an integrated lighting system and changing programs. She employs artificial intelligence to translate the data from environment  into an immersive and interactive light and color. Also, the inhabitable structure provides various points of engagement; transformational views when audience descends the stairs, pause, productivity, and reflection at the base of the sculpture.  I admire how she breaks down the barriers of disciplines and create a integrated work of engineering, architecture, biology, and mathematics. Especially, how she branches “knitting” into structural and architectural applications is very creative and compelling as it’s not a common material used in architecture.

https://www.jennysabin.com/sinewflex

Sinew Flex

Looking Outwards – 09

I admire the project Active Ecosystem (SMF) by Camille Utterback and Michelle Higa Fox created in 2011 for Sacramento International Airport’s ticketing hall. I like how it continues the surrounding structure’s idea of “bringing the outside in”. It shows the interest of its maker in its inspiration: the “cycles of growth, movement, and decay in the natural agricultural environment or Sacramento”. The piece changes in response to multiple factors including the elevator that it surrounds, the time of day, and seasons. The piece combines hand drawn animations and dynamic calculations to generate the movement of growing or moving. It embodies the Utterback’s goal of creating physical-digital stems that engage surrounding and people’s bodies instead of just grasping attention of passerbyers. Camille Utterback is an artist with a focus on digital and interactive art. She explores possibilities of linking computational systems to human movement and physicality in many ways. Utterback combines sensing and display technology with custom software. She has a BA from Williams College and an MPS degree from the Interactive Telecommunications Program from New York University.

Active Ecosystem (SMF) | Camille Utterback

Camille Utterback and Michelle Higa Fox piece for Sacramento International Airport. The animations change based on its surrounds, the time of day, and seasons. When the seasons or outside conditions change the type of fish changes and in the spring there is drifting pollen instead of fall’s falling leaves.

Bhaboo’s Looking Outwards – Week 9

I really enjoyed looking into this week’s “looking outwards” because the work women and non-binary people are doing around the world is INCREDIBLE. After looking through a lot of the work of these people, I decided to look more into Chloe Vardlidi who loves “designing and building playful products that empower humans to be creative, kind and curious about the world around them.”

A project she worked on, “The Littlebits Codekit + App” caught my eye quickly on their website because it helps teachers teach younger children by engaging them with fun games and cool entertainment. Using this kit, paired with the app, kids can create games and make inventions like a keytar instrument, hot potato, or button master. I find it really cool that Chloe was able to partner up with the company Sphero to work on a project of these level.

Link to Chloe’s Website
Link to the Project

Looking Outwards -09 : A Focus on Women and Non-binary Practitioners in Computational Art

I really admire Camille Utterback’s project Text Rain not because of the complexity of the program itself, but when the project is produced. First, I need to introduce who Camille is. She is an American Interactive Installation artist who graduated from William College and gained her master’s degree from the Interactive Telecommunications Program at New York University’s Tisch School of the Arts. Why I prefer her Text Rain installation is because her work is groundbreaking or one of the first of such type (Interactive Installation). Her work might not look impressive at our time, since her program is basically about capturing the silhouette of pedestrians and making random letters float on them. However, because of this “simple” (compared to nowadays interactive projects) installation, which was created during 1999, more and more interactive public installations that we might see on streets were created, making Camille Utterback a pioneer of such computational forms of art.

Text Rain – by Camille Utterback and Romy Achituv:

Link: http://camilleutterback.com/projects/text-rain/

Project 09: Computational Portrait

My process: I chose a picture of me on my 3rd birthday. I wanted to incorporate the number 3 into my custom pixel portrait. So I started there. My first custom pixels are made of 3s. Then I started to play with the other ways I could deconstruct, rebuild, and recolor play with the other ways I could deconstruct, rebuild, and recolor my portrait. I have created a 5 Portrait Series.

Portrait 1 – Made of Threes, Portrait 2 – Made of Ovals – inspired by thumbprint art, Portrait 3 – Made of Squares, Portrait 4 – Made of Legos – inspired by Legos, Portrait 5 – Made of Warhol – inspired by Andy Warhol

Press the space bar to see the various portraits I created. Click the mouse to freeze the creation of a portrait. Click again to resume.

sketch
/* Evan Stuhlfire
 * estuhlfi@andrew.cmu.edu section B
 * Project-09: Computational Portrait */

/* My process: I chose a picture of me on my 3rd 
 * birthday. I wanted to incorporate the number 3 into
 * my custom pixel portrait. So I started there. My first custom pixels
 * are made of 3s. Then I started to 
 * play with the other ways I could deconstruct, rebuild, and recolor
 * my portrait. I have created a 5 Portrait Series. */

 /* Portrait 1 - Made of Threes
  * Portrait 2 - Made of Ovals - inspired by thumbprint art
  * Portrait 3 - Made of Squares
  * Portrait 4 - Made of Legos - inspired by Legos
  * Portrait 5 - Made of Warhol - inspired by Andy Warhol */

/* Press the space bar to see the various portraits I created.
 * Click the mouse to freeze the creation of a portrait. Click again
 * to resume. This way portraits can be saved in different states. */

var img; // image variable
var scaleCanvas = 1.4; // factor to make canvas bigger than image

// booleans to determin which portrait to draw
var dThrees = true;
var dEllipses = false;
var dSquares = false;
var dLines = false;
var dOutline = false;

// used with a mouse click to freeze and resume dynamic portraits
var freeze = false; 

function preload() {
    img = loadImage("https://i.imgur.com/FRtQdiE.jpg");
}

function setup() {
    // create canvas 1.4 times the size of the original image
    createCanvas(img.width * scaleCanvas, img.height * scaleCanvas);
    background(230);

    textAlign(CENTER);
}
    
function draw() {
    // randomly generate x and y to get color from

    // use randomGaussian so image appears in center first
    var xPos = Math.floor(randomGaussian(img.width/2, 100));
    var yPos = Math.floor(randomGaussian(img.height/2, 100));

    // remap coordinates of image to the canvas size
    var xMap = map(xPos, 0, img.width, 0, width);
    var yMap = map(yPos, 0, img.height, 0, height);

    // get pixel color
    var pixCol = img.get(xPos, yPos);

    // test which syle to draw
    if(dThrees & !freeze) {
        drawThrees(xMap, yMap, pixCol);
    } else if(dEllipses & !freeze) {
        drawEllipses(xMap, yMap, pixCol);
    } else if(dSquares & !freeze) {
        rectMode(CENTER);
        drawSquares(xMap, yMap, pixCol);
    } else if(dLines & !freeze) {
        drawLines();
    } else if(dOutline & !freeze) {
        rectMode(CORNER);
        drawOutline();
    }
}

function keyPressed() {
    // switch between portait drawings when
    // the space bar is pressed
    if(key != " ") {
        // key was not space bar, return
        return;
    }

    if(dThrees){
        dThrees = false;
        dEllipses = true;
        dSquares = false;
        dLines = false;
        dOutline = false;
    } else if(dEllipses) {
        dThrees = false;
        dEllipses = false;
        dSquares = true;
        dLines = false;
        dOutline = false;
    } else if(dSquares) {
        dThrees = false;
        dEllipses = false;
        dSquares = false;
        dLines = true;
        dOutline = false;
    } else if(dLines) {
        dThrees = false;
        dEllipses = false;
        dSquares = false;
        dLines = false;
        dOutline = true;
    } else if(dOutline) {
        dThrees = true;
        dEllipses = false;
        dSquares = false;
        dLines = false; 
        dOutline = false; 
    }
    // reset background, unfreeze if frozen
    background(230);
    freeze = false;
}

function mousePressed() {
    // toggle the freeze boolean to freeze drawing
    freeze = !freeze;
}

function colorShift(pc, shiftType) {
    // read the pixel color variable and shift the color
    // based on shiftType specified
    var r, g, b, t;

    // read colors
    r = pc[0];
    g = pc[1];
    b = pc[2];
    t = pc[3];

    if(shiftType == "green") {
        // shift colors towards green
        r = constrain(r - 10, 5, 200);
        g = constrain(g + 50, 50, 230);
        b = constrain(b + 10, 10, 200);  
    } else if(shiftType == "blue") {
        // shift colors towards blue
        r = constrain(r - 10, 5, 200);
        g = constrain(g + 10, 10, 200);
        b = constrain(b + 50, 50, 230);        
    }

    // map mouse to change trasparancy as it moves vertical
    var my = map(mouseY, 0, height, 50, 180);
    t = my;

    return color(r, g, b, t);
}

function drawThrees(xMap, yMap, pixCol) {
    // draw portrait out of 3s
    var maxSize = 40;

    // green shift colors from original image
    pixCol = colorShift(pixCol, "green");
    stroke(pixCol);
    strokeWeight(1);
    fill(pixCol);
    // map mouse x to new range to control text size
    var mx = map(mouseX, 0, width, 10, maxSize);
    textSize(min(mx, maxSize));

    // draw 3s on canvas
    text("3", xMap, yMap);
}

function drawEllipses(xMap, yMap, pixCol) {
    // draw portrait out of random ellipses

    // blue shift colors from original image
    pixCol = colorShift(pixCol, "blue");
    // use color for fill
    fill(pixCol);
    stroke(pixCol);
    strokeWeight(1);
    ellipse(xMap, yMap, random(5, 35), random(5, 15));
}

function drawSquares(xMap, yMap, pixCol) {
    // create portrait from squares
    // square size is based on the darkness of the pixel color
    var maxColor = 140;
    var midColor = 100;
    var midColor2 = 70;

    // make color more or less transparent with movement of mouseY
    var transColor = colorShift(pixCol, "");
    // set colors
    stroke(transColor);
    fill(transColor);

    // Check pixel color and adjust square size based on how dark color is
    if(pixCol[0] > maxColor & pixCol[1] > maxColor && pixCol[3] > maxColor) {
        square(xMap, yMap, 30);
        fill(pixCol);
        circle(xMap, yMap, 5);
    } else if(pixCol[0] > midColor & pixCol[1] > midColor && pixCol[3] >
        midColor) {
        square(xMap, yMap, 20);
        fill(pixCol);
        circle(xMap, yMap, 5);
    } else if(pixCol[0] > midColor2 & pixCol[1] > midColor2 && pixCol[3] >
        midColor2) {
        square(xMap, yMap, 15);
        fill(pixCol);
        circle(xMap, yMap, 5);
    }else {
        square(xMap, yMap, 20);
        fill(pixCol);
        circle(xMap, yMap, 5);
    }
}

function drawLines() {
    // lego like circles and square in rows and columns
    for(var y = 5; y < img.height; y += 5) {

        for(var x = 5; x < img.width; x += 5) {
            var c = img.get(x, y);

            // map x from img to x from canvas
            var mx = map(x, 0, img.width, 0, width);
            // map y from img to y from canvas
            var my = map(y, 0, img.height, 0, height);

            // fill and draw 
            // shift to lego colors   
            if(c[0] > 180) {
                c = color(255, 255, 0);
            } else if(c[0] > 80) {
                c = color(0, 255, 0);
            } else if(c[0] > 50) {
                c = color(255, 0, 0);
            } else {
                c = color(0, 0, 255);
            }
            fill(c);
            noStroke();
            rect(mx, my, 10, 10);
            stroke(50);
            circle(mx, my, 5);
        }
    }
}

function drawOutline() {
    // draw an Andy Warhol style grid of pixel faces
    // draw four color quadrants
    fill(0, 255, 0); // green
    rect(0, 0, width/2, height/2);
    fill(255, 255, 77); // yellow
    rect(width/2, 0, width, height/2);
    fill(77, 255, 255); // blue
    rect(0, height/2, width/2, height);
    fill(255, 148, 77); // orange
    rect(width/2, height/2, width, height);

    // draw monochrome points at points of color change
    for(var y = 0; y < img.height; y += 3) {
        // get color from image
        var c = img.get(0, y);

        // look ahead to see when to change line color
        for(var x = 0; x < img.width; x += 2) {
            var dc = img.get(x, y);

            // color is different, draw this point
            if(dc[0] - c[0] > 10 || c[0] - dc[0] > 10 || 
                x == img.width - 1) {
                // map x from img to x from canvas
                var mx = map(x, 0, img.width, 0, width);
                // map y from img to y from canvas
                var my = map(y, 0, img.height, 0, height);

                if(c[0] > 60) {
                    drawPointImg(mx, my, color(0, 0, 230), 1);
                    drawPointImg(mx, my, color(230, 0, 230), 2);
                    drawPointImg(mx, my, color(255, 0, 0), 3);
                    drawPointImg(mx, my, color(255, 216, 204), 4);
                }

                // set color variable to new color
                c = dc;
            }
        }
    }
}

function drawPointImg(mx, my, pc, quad) {
    // draw set of points for specified quadrant 
    // map to specified quad
    if(quad == 1) {
        // map points to first quadrant
        qmx = map(mx, 0, width, 0, width/2);
        qmy = map(my, 0, height, 0, height/2);
    } else if (quad == 2) {
        // map points to second quadrant
        qmx = map(mx, 0, width, width/2, width);
        qmy = map(my, 0, height, 0, height/2);
    } else if (quad == 3) {
        // map points to third quadrant
        qmx = map(mx, 0, width, 0, width/2);
        qmy = map(my, 0, height, height/2, height);
    } else if (quad == 4) {
        // map points to fourth quadrant
        qmx = map(mx, 0, width, width/2, width);
        qmy = map(my, 0, height, height/2, height);
    }

    // set color of point
    stroke(pc);
    strokeWeight(.25);

    // draw point
    point(qmx, qmy);
}


Project Notes

LO 09: Focus on Women and Non-binary Practitioners

Allison Parish is a programmer, poet, and an Assistant Arts Professor at NYU. She creates projects that combine language with software and machine learning. She has written multiple books and articles, created a card game called Rewordable, and presented at Eyeo 2015. Her body of work spans writing multiple pieces of custom software that generate poetry or manipulate language. For example, she has written a Nonsense Laboratory tool which allows users to manipulate words in both how they are spelled and how they sound. The goal is to allow users to play with spelling the same way people play musical instruments or play with modeling clay. The project evokes linguistic creativity and explores machine learning.

To create her projects, Parish accesses large language datasets found in the open source Gutenberg Project and in online movie databases. The project I enjoyed most was her Semantic Similarity Chatbot. This chatbot accesses several movie dialog datasets available through Google. The project is written in Python and uses the spaCy add-on library. It builds word vectors to generate a list of possible responses to a chat. The delivered response then is randomly chosen from the possible vectors. All of the code is available on github and there is a google colab page setup to download and run the chatbot. I had several conversations with the chatbot. The responses are somewhat random and don’t seem very relevant; however, the project remains very interesting and is important as a foundation for machine learning and future chatbots. One of my chats is included below. My entries are shown next to the happy face emoji. The chatbot responses are next to the robot emoji.

Chatbot Output.

Project 09: Computational Portrait (Custom Pixel)

This process took me a while to figure out and understand. I wanted it to be interactive in some way and thought, what if you get to “paint” it?”. To my surprise, I was able to figure out the painting portion quite easily. I also wanted the pixels to be more than just squares or circles so I decided to use a phrase that I constantly need to be reminded of: “Believe in yourself”.

sketch my portraitDownload
/*
Sandy Youssef; 
section D; 
syoussef@andrew.cmu.edu;
Project-09;
*/

// loads portrait of my face
function preload () {
    face = loadImage ("https://i.imgur.com/47iZQND.jpeg");

}


function setup() {
    createCanvas(480, 480);
    background(220);
    face.resize(480,480); // resizes image proportionally to the canvas
    face.loadPixels(); // loads pixels data
}

function draw() {
        
    // pixels appear at the position of the mouse
    var ColorPixel = face.get(mouseX,mouseY);  // returns text that corresponds to the color of the image at the location of the mouse
    noStroke();
        
    // Array that contains words of a phrase. This allows the individual words to 
    //be displayed on the canvas as opposed to the phrase as a whole to 
    //create shorter sized "pixels"
    word = ["Believe", "In", "Yourself"];
    // loop that continues to iterate over the words 
    for(var i = 0; i < 3; i ++) {
        //draws text random size wherever your mouse is on the canvas
        // allows you to paint the portrait!
        fill(ColorPixel);
        textSize(random(1,10));
        text(word[floor(random(word.length))], mouseX,mouseY);
            

    }


    
}

// This process took me a while to figure out and understand. 
// I wanted it to be interactive in some way and I thought "what if you get to "paint" it?"
//  To my surprise, I was able to figure out the painting portion quite easily. I also wanted the 
//  pixels to be more than just squares or circles so I decided to use a phrase that I constantly need to be reminded of: "Believe in yourself" 



  
   
  
What it will look like once fully painted

Original Portrait

Looking Outwards 09: A Focus on Women and Non-binary Practitioners in Computational Art 

Creator’s Name: Toni Dove
Title of Work: The Dress That Eats Souls
Year of Creation: Feb 2018

This eerie yet beautiful piece of art is incredible to look at and the experience of interacting with it seems to be quite as impressive. While many concepts are spoken about through this dress with a robotic bodice, it explores our interaction with technology, so powerful, it has the potential to consume us and our experiences. When an individual stands in front of this dress, it mimics their motion, and POV video allows the person to watch through the eyes of those who have worn the dress and hear their inner thoughts. To create this dress it must not only be built physically to make certain movements but programmed to replicate the movements of others which is quite impressive.


Toni Dove works in New York to make interface technologies that create interactive performances. She has worked on many installations and she describes The Dress That Eats Souls as “an interactive cinema and robotics installation”

https://tonidove.com/the-dress-that-eats-souls/text/

Images of the dress

Project 9 – Computational Portrait

This portrait is based on the idea of the probabilistic road map as described in ‘Probabilistic Roadmap Path Planning’ by H. Choset et al. where the figure in the portrait is graph G and the red background are obstacles/collisions.

Controls

  • RIGHT ARROW = advance drawing one step
  • ENTER = start & stop drawing
  • ‘r’ = refresh
sketch
//Name: Tsz Wing Clover Chau
//andrewid: ctchau
//Section E
//Project 9


var chosenPixels;
var step;

var bgPx = [];
var rStep;

var range = 30;
var baseImage;


function preload(){
    baseImage = loadImage("https://i.imgur.com/PaF0PFq.png");
}

function setup(){
    createCanvas(480, 480);
    background(255);
    frameRate(30);
    baseImage.loadPixels();

    //init array
    chosenPixels = [];
    bgPx = [];
    step = false;
    rStep =  random(0, 30);

    for (var i = 0; i < rStep; i++){
        pt = makePoint(int(random(0, 480)), int(random(0, 480)));
        if (isRed(pt)) {
            bgPx.push(pt);
        } else {
            chosenPixels.push(pt);
        }
    }
}


function draw() {
    drawBg();
    if (keyIsDown(RIGHT_ARROW) || step){   // press right arrow to invidually step
        addPx();
    }
    drawFace();
}


//HELPER FUNCTIONS
function makePoint(px, py){
    var pt = {x: px, y: py};
    pt.c = baseImage.get(px, py);
    pt.neighbors;
    return pt;
}

function addPx(){
    rStep =  random(0, 100);
    var newPx = 0;
    while (newPx < rStep){
        pt = makePoint(int(random(0, 480)), int(random(0, 480)));

        //add to bg array + pick new if red
        while (isRed(pt)){
            if (int(random(0, 8)) == 1){
                bgPx.push(pt);
            }
            pt = makePoint(int(random(0, 480)), int(random(0, 480)));
        }

        var min_dist = range;
        for (var j = 0; j < chosenPixels.length; j++){
            var checkPx = chosenPixels[j];
            var d = dist(checkPx.x, checkPx.y, pt.x, pt.y);
            
            if ((dist(checkPx.x, checkPx.y, pt.x, pt.y) < range) & (d < min_dist)){
                min_dist = d;
                stroke(pt.c);
                strokeWeight(0.5);
                line(checkPx.x, checkPx.y, pt.x, pt.y);
                chosenPixels.push(pt);
                newPx ++;
                break;
            }
        }
    }
}


function isRed(pt){
    if (pt.c[0] > 50 & pt.c[1] < 30){
        return true;
    }
    return false;
}

function keyPressed(){
    if (keyCode == ENTER){  //ENTER to autocomplete
        step = !step;
    } else if (key == 'r'){  //press 'r' to reset!
        setup();
    }
}



function drawBg(){
    for (var i = 0; i < bgPx.length; i++){
        px = bgPx[i];
        px.c[3]= 80;
        stroke(px.c);
        strokeWeight(0.3);
        if (int(random(0,2)) == 1){
            line(px.x, 0, px.x, height);
        } else {
            line(0, px.y, width, px.y);
        }
    }
}

function drawFace(){
    for (var i = 0; i < chosenPixels.length; i++){
        var curPx = chosenPixels[i];
        stroke(curPx.c);
        strokeWeight(5);
        point(curPx.x, curPx.y);
    }
}

Logic/Pseudocode:

  • Configuration q = series of randomly generated non-background pixels (ie. not red).
  • Q = new randomly generated non-background pixels
    • if distance from q -> Q < acceptable range, append to q
  • N = rStep (ie. no. of new non-background pixels added to q)
Probabilistic Roadmap Path Planning by H. Choset et Al
Probabilistic Roadmap Path Planning by H. Choset et Al

References:
http://www.cs.columbia.edu/~allen/F15/NOTES/Probabilisticpath.pdf