Looking Outwards 11: Societal Impacts of Digital Art

The societal issue is in regards to copyright and how NFTs impact it. One example is how NFTs occasionally steal work from commissioned artists without their consent or permission, such as in the case of Jason Rohrer using the work of artists without their consent to sell NFTs. The article begins by detailing what NFTs are; unique tokens, most commonly a URL of some digital media which are given to individuals for ownership. However—and this is the conflict that the article highlights—that very ownership has a lot more to take into account than what the original developers may have intended. Those who have NFTs don’t actually have copyright of their NFTs, and their so-called products are still accessible and distributable to the public. To make matters worse, thousands can release unoriginal NFTs based off of digital URLs in a market that doesn’t restrict or legislate the selling and distribution of NFTs.

Link to article here

Project 11-Generative Landscape

sketch
/* Evan Stuhlfire 
 * estuhlfi@andrew.cmu.edu section B
 * project-11-generative landscape */

var hills = [];
var trees = [];
var chickArray = [];
var imgArray = [];
var farm = [];
var barnImg;
var cowImg;
var planeObj;
var flyingPlane = false;

var scrollSpeed = 5;

function preload(){
    // preload images

    // URLs to imgur walking chick
    // Chick image licensed from Adobe stock images
    var filenames = [];
    filenames[0] = "https://i.imgur.com/kjBGzBF.png";
    filenames[1] = "https://i.imgur.com/hxvbkWZ.png";
    filenames[2] = "https://i.imgur.com/53MK7g1.png";
    filenames[3] = "https://i.imgur.com/6nrYJCw.png";
    filenames[4] = "https://i.imgur.com/XmPcBDa.png";
    filenames[5] = "https://i.imgur.com/3OusOsv.png";

    for (var i = 0; i < filenames.length; i++) {
        imgArray[i] = loadImage(filenames[i]);

    barnImg = loadImage("https://i.imgur.com/inS5Xdt.png");
    cowImg = loadImage("https://i.imgur.com/8XjQyMt.png");

    }
}

// methods
function stepChick() {
    // update the chick image to animate
    if(this.imgNum < chickArray.length - 2) {
        // increment to next image
        this.imgNum++;
    } else {
        // if at end of array reset to beginning
        this.imgNum = 0; 
    }
}

function drawChick() {
    // draw image
    image(imgArray[this.imgNum], this.x, this.y, 50, 50);
}

function drawOneHill() {
    // draw hill
    fill(this.c);
    stroke(0, 150, 0);
    strokeWeight(1);
    ellipse(this.x, this.y, this.w, this.hi);

    this.x -= this.s; // decrement by speed
}

function drawTree() {
    // draw trunk
    stroke(77, 38, 0);
    strokeWeight(3);
    line(this.x, this.y, this.x, this.y + (this.h * .8));
    line(this.x, this.y + this.h * .5, this.x + this.w * .2, 
        this.y + this.h * .2);
    line(this.x, this.y + this.h * .7, this.x - this.w * .1, 
        this.y + this.h * .1);

    // draw leaves
    fill(this.c);
    stroke(0, 100, 0);
    strokeWeight(1);
    ellipse(this.x, this.y, this.w, this.h);

    this.x -= this.speed; // decrement by speed
}

// object constructor functions
function newChick(cx, cy) {
    // constructor to make a chick
    var c = {x: cx, y: cy,
            imgNum: 0,
            stepFunction: stepChick,
            drawFunction: drawChick
        }
    return c;
}

function newHill(hx, hy, hw, hhi, hc, hs) {
    // create new hill at x, y with diameter d
    var h = {x: hx, y: hy, w: hw, hi: hhi, 
            c: hc, s: hs,
            drawFunction: drawOneHill
        };
    return h;
}

function newTree(tx, ty, tw, th, tc, ts) {
    // create new tree at x, y of height th, color tc
    // tree width = tw, tree speed = ts
    var t = {x: tx, y: ty, w: tw, h: th, c: tc, 
            speed: ts,
            drawFunction: drawTree
        };
    return t;
}

function newFarm(fx, fy, fi, fw, fh, fb) {
    // create new farm img at x, y
    // use farm image fi
    var f = {x: fx, y: fy, img: fi,
            w: fw, h: fh,
            speed: scrollSpeed,
            barn: fb
        };
    return f;
}

function newPlane(px, py, pdx, pdy) {
    // create plane object
    var p = {x: px, y: py, dx: pdx, dy: pdy};
    return p;
}

function setup() {
    createCanvas(480, 480);
    frameRate(10);
    imageMode(CENTER);

    // loop to create chick images
    for(var i = 0; i < imgArray.length; i++) {
        chickArray[i] = newChick(width/2, height * .7);
    }

    var onCanvas = true;
    // generate initial hills
    var numHills = floor(random(15, 20));
    // onCanvas = true for first set of hills to draw on canvas
    generateHills(onCanvas, numHills); 

    // create a farm
    generateFarm();

    // generate initial trees
    var numTrees = floor(random(1, 10));
    // onCanvas = true trees drawn on canvas
    generateTrees(onCanvas, numTrees, 1);
    generateTrees(onCanvas, numTrees, 2);
    generateTrees(onCanvas, numTrees, 3);
}

function draw() {
    // call all the parts of the scrolling background
    background(153, 179, 255);
    drawSun();
    // draw hills
    drawHills();
    removeHills();
    createNewHills();

    foreground();
    
    // draw farm elements, barns and cows
    drawFarm();
    removeFarm();
    createNewFarm();

    // draw trees
    drawTrees();
    removeTrees();
    createNewTrees(1);
    createNewTrees(2);
    createNewTrees(3);

    // animate the little chick
    drawLittleChick();

    // draw plane
    createPlane();
    drawPlane();
}

function drawSun() {
    // draw stationary sun
    fill(255, 255, 77, 200);
    stroke(255, 255, 26);
    strokeWeight(1);
    ellipse(width * .85, height * .1, 50, 50);
}

function foreground(){
    // draw grass
    fill(0, 153, 51);
    noStroke();
    rect(0, height/3, width, height);
    // draw path
    stroke(153, 102, 51);
    strokeWeight(20);
    line(0, height * .75, width, height * .75);
    // draw pebbles
    // generate differnt shades of tan
    stroke(random(210, 250), random(125, 220), random(85, 220));
    strokeWeight(3);
    var y = floor(random(height * .75 - 10, height * .75 + 10));
    var x = floor(random(0, width));
    point(x, y);
}

function drawLittleChick() {
    // loop through chick array call step and draw methods
    for(var i = 0; i < chickArray.length; i++) {
        var currentChick = chickArray[i];
        currentChick.stepFunction();
        currentChick.drawFunction();
    }
}

function createPlane() {
    // probability of a plane
    var newPlaneLikely = .0008;
    if(random(0, 1) < newPlaneLikely & !flyingPlane) {
        var y = floor(random(40, 100));
        var x = 0;
        var dx = random(2, 5);
        var dy = random(.1, .8);
        planeObj = newPlane(x, y, dx, dy);
        flyingPlane = true;
    }
}

function drawPlane() {
    if(flyingPlane) {
        stroke(230, 255, 255);
        strokeWeight(3);
        line(planeObj.x, planeObj.y, planeObj.x + 30, planeObj.y - 2);
        // draw wings
        strokeWeight(1);
        line(planeObj.x + 18, planeObj.y - 2, planeObj.x + 3, 
            planeObj.y + 5);
        line(planeObj.x + 18, planeObj.y - 1, planeObj.x + 20, 
            planeObj.y - 10);
        // draw tail
        line(planeObj.x, planeObj.y, planeObj.x - 3, planeObj.y -8);

        planeObj.x += planeObj.dx;
        planeObj.y -= planeObj.dy; 

        if(planeObj.x > width || planeObj.y < 0) {
            flyingPlane = false;
        }
    }

}

function createNewHills() {
    // probability of a hill
    var newHillLikely = .07;
    if(random(0, 1) < newHillLikely) {
        var numHills = floor(random(5, 12));
        var onCanvas = false;
        generateHills(onCanvas, numHills);
    }
}

function removeHills() {
    // if array has more items and hills have scrolled off screen
    var keep = [];

    if(hills.length >= 0) {
        for(var i = 0; i < hills.length; i++) {
            if(hills[i].x + hills[i].w/2 > 0) {
                keep.push(hills[i]);
            }
        }
        hills = keep;
    }
}

function drawHills() {
    // draw hills on canvas
    for(var i = 0; i < hills.length; i++) {
        var h = hills[i];
        h.drawFunction();
    }
}

function generateHills(onCanvas, num) {
    // if onCanvas = true then generate first set of hills
    // on canvas, otherwise generate off canvas

    // generate num number of new hills
    for(var i = 0; i < num; i++) {
        // generate hill color
        var g = floor(random(50, 230));
        var c = color(80, g, 0);

        // generate x, y, width, and height of hill
        var y = random(height/2.6, height/2);
        var w = random(100, width);
        var h = random(150, 250);

        if(onCanvas) {
            // generate hills on canvas
            var x = random(-w, width + w * 3);
            var w = random(width/2, width);
        } else {
            // generate hills off canvas
            var x = random(width + (w * 1.5), width * 3); 
        }

        var hill = newHill(x, y, w, h, c, 5);
        hills.push(hill);
    }
}

function createNewFarm(){
    // probability of a farm
    var newFarmLikely = .01;
    if(random(0, 1) < newFarmLikely) {
        generateFarm();
    }
}

function removeFarm() {
    // if array has more items and farms have scrolled off screen
    var keep = [];

    if(farm.length >= 0) {
        for(var i = 0; i < farm.length; i++) {
            if(farm[i].x + farm[i].w > 0) {
                keep.push(farm[i]);
            }
        }
        farm = keep;
    }
}

function generateFarm() {
    // create cows on farm
    var isBarn = false
    var numCows = floor(random(10, 30));
    for(var i = 0; i < numCows; i++) {
        // create a cow object and add it to the farm
        // array for each cow
        var x = random(width, width * 4);
        var y = random(height/2.2, height/3.5);

        if(y < height/2.7) {
            // make cows smaaller, they are further away
            var w = random(10, 15);
            var h = random(10, 15);
        } else {
            // make cows bigger, they are closer
            var w = random(25, 30);
            var h = random(25, 30);
        }

        var c = newFarm(x, y, cowImg, w, h, isBarn);
        farm.push(c);
    }

    // randomly generate barn variables
    var x = random(width + w, width * 2);
    var y = random(height/2.6, height/3.7);

    // if barn is further away, draw it smaller
    if(y < height/3.2) {
        var w = random(20, 40);
        var h = random(20, 40);
    } else {
        // close and bigger
        var w = random(60, 90);
        var h = random(50, 70);
    }

    isBarn = true;
    var f = newFarm(x, y, barnImg, w, h, isBarn);
    farm.push(f);
}

function drawFarm() {
    // draw farm on canvas
    var barnArray = [];
    if(farm.length > 0) {
        for(var i = 0; i < farm.length; i++) {
            var f = farm[i];
            if(f.barn) {
                barnArray.push(f);
            } else {
                // draw cows behind barns
                image(f.img, f.x, f.y, 
                    f.w, f.h);
                f.x -= f.speed; 
            }
        }
        // draw barns in their own layer on top of cows
        for(var i = 0; i < barnArray.length; i++) {
            var b = barnArray[i];
            image(b.img, b.x, b.y, b.w, b.h);
            b.x -= b.speed;
        }
        barnArray = [];
    }
}

function createNewTrees(layer) {
    var newTreeLikely = .012;
    var numTrees = floor(random(2, 4));
    // send false to generate off canvas
    var onCanvas = false;

    if(random(0, 1) < newTreeLikely) {
        generateTrees(onCanvas, numTrees, layer);
    }
}

function removeTrees() {
    // if array has more items and trees have scrolled off screen
    var keep = [];
    if(trees.length >= 0) {
        for(var i = 0; i < trees.length; i++) {
            if(trees[i].x + trees[i].w > 0) {
                keep.push(trees[i]);
            }
        }
        trees = keep;
    }
}

function drawTrees() {
    // draw trees on canvas
    if(trees.length >= 0) {
        for(var i = 0; i < trees.length; i++) {
            var t = trees[i];
            t.drawFunction();
        }
    }
}

function generateTrees(start, num, layer) {
    // if start = true then generate first set of trees
    // on canvas, otherwise generate off canvas

    // generate num number of new trees
    for(var i = 0; i < num; i++) {
        // generate tree color
        var r = floor(random(70, 100));
        var g = floor(random(80, 255));
        var b = floor(random(80, 120));
        if(layer == 1) {
            var c = color(r, g, b, 190); 
            // create big trees in background
            bigTrees(start, c);
        } else if(layer == 2) {
            r = floor(random(0, 150));
            g = floor(random(50, 150));
            b = floor(random(250, 255));
            var c = color(r, g, b, 190);
            // create little trees in midground
            littleTrees(start, c);
        } else {
            r = floor(random(250, 255));
            g = floor(random(30, 150));
            b = floor(random(80, 255));
            var c = color(r, g, b, 200);
            // create shrubs in foreground
            shrubs(start, c);
        }
    }
}

function bigTrees(start, c) {
    // generate x, y, width, and height of trees
    var w = random(50, 70);
    var h = random(40, 70); 

    var y = random(height/2.6, height/2.8);

    if(start) {
        // generate trees on canvas
        var x = random(5, width); 
    } else {
        // generate trees off canvas
        var x = random(width + w/2, width * 3); 
    }

    // create tree and add to array
    var tree = newTree(x, y, w, h, c, 5);
    trees.push(tree);
}

function littleTrees(start, c) {
    // generate x, y, width, and height of trees
    var w = random(30, 40);
    var h = random(15, 40); 

    var y = random(height/1.7, height/2);

    if(start) {
        // generate trees on canvas
        var x = random(5, width); 
    } else {
        // generate trees off canvas
        var x = random(width + w/2, width * 2); 
    }

    // create tree and add to array
    var tree = newTree(x, y, w, h, c, 5);
    trees.push(tree);
}

function shrubs(start, c) {
    // generate x, y, width, and height of trees
    var w = random(20, 40);
    var h = random(15, 20); 

    var y = random(height/1.1, height/1.3);

    if(start) {
        // generate trees on canvas
        var x = random(5, width); 
    } else {
        // generate trees off canvas
        var x = random(width + w/2, width * 3); 
    }

    // create tree and add to array
    var tree = newTree(x, y, w, h, c, 5);
    trees.push(tree);
}

Looking Outward – 11: NFTs

Non-fungible Tokens, NFTs, gave the promise of increased income and a secure line of ownership to digital art creators. The idea was presented as a way for digital artists to reap the benefits of income and ownership that physical artists enjoy. This promised to elevate their work and to reduce copyright infringement by establishing a secure chain of ownership and proof of creation. Thus far, NFTs have failed to deliver on this promise, and in their current state, they are at best an experiment in the application of blockchain technology. At worst, they are a fad or even a fraud.

Jonathan Bailey outlines the rise and promise of NFTs in his article, “NFTs and Copyright”, which appeared in the March 16, 2021 edition of Plagiarism Times. Although NFTs have existed since 2017, they took the world by storm in 2021 with famous artists, such as Beeple, CEOs such as Twitter’s Jack Dorsey, and celebrities such as William Shatner, selling NFTs for millions of dollars. The word “non-fungible” means that something is not interchangeable, implying uniqueness. However, on the current NFT exchanges, anything can be tokenized, including URLs, images, and tweets. When something is tokenized a transaction is created on a blockchain. This makes the token unique, but only the token is unique. The original work that the token is linked to can be duplicated again and again.

Furthermore, the token does not confer ownership of the original work. When the token is sold, the original content can still be copied or owned by someone else. This creates ethical and copyright issues. These issues arise when people, or at times bots, tokenize and sell content they do not own. Some NFT exchanges attempt to prohibit unauthorized NFT sales, but many do not. This is copyright infringement and theft. A further ethical problem arises when NFTs are misrepresented to unknowing buyers. Many buyers believe they own the artwork or its copyright rather than just a transaction on a blockchain. Ultimately, it is a buyer’s responsibility to learn, however deliberate deception is ethically wrong.

NFTs could achieve their original promise and provide digital artists with income and protection; however, it would take a different implementation than what is now being pursued. In its current form, the NFT market will require artist and buyer protections or it will likely fade as another passing fad.

Project 11

Scrolling environment in space

sketch
//PLANET VARIABLES:
var numPlanets = 4;
var planet = {x: [], y: [], s: [], r: [], g: [], b: [], dx: []};
var d = [];

//STAR VARIABLES:
var numStars = 100;
var star = {x: [], y: [], s: [], dx: []};

//IMG VARIABLES:
var porthole;
var astroLinks = ["https://i.imgur.com/FrLKzou.png",
				  "https://i.imgur.com/vdhX4kE.png",
				  "https://i.imgur.com/01Kk3J7.png"];
var astroPics = [];
var astro = {x: [], y: [], s: [], dx: [], e: []};

function preload(){
	for(k = 0; k < 3; k++){
		astroPics[k] = loadImage(astroLinks[k]);
	}
	porthole = loadImage("https://i.imgur.com/YSSOdgW.png") //made this porthole graphic myself
}

function setup() {
    createCanvas(480, 480);
    background(0);
    planetInitialize();
    starInitialize();
    astroInitialize();
}

function draw() {
	background(0);
	starUpdate();
	planetUpdate();
	astroUpdate();
	image(porthole, 0, 0, width, height);
}

function drawPlanetA(x, y, s, i){ //option one for planet type (moon-y)
	strokeWeight(0);
	fill(planet.r[i], planet.g[i], planet.b[i]); //randomized color
	ellipse(x, y, s, s);
	fill(planet.r[i] + 20, planet.g[i] + 20, planet.b[i] + 20); //randomized color, but a little bit lighter
	ellipse(x - s/10, y + s/3, s/4);
	ellipse(x + s/5, y - s/10, s/3);
	ellipse(x - s/4, y - s/5, s/7);
}

function drawPlanetB(x, y, s, i){ //option two for planet type (saturn-y)
	fill(planet.r[i], planet.g[i], planet.b[i]);
	ellipse(x, y, s, s);
	strokeWeight(3);
	stroke(255-planet.r[i], 255-planet.g[i], 255-planet.b[i]);
	line(x - s*(2/3), y, x + s*(2/3), y);
	strokeWeight(0);
}

function starUpdate(){
	for(var j = 0; j < numStars; j++){
		strokeWeight(0)
		fill(250, 248, 235); //creamy white
		ellipse(star.x[j], star.y[j], star.s[j], star.s[j]);

		if(star.x[j] >= width + star.s[j]){ //if star has fully moved off screen, I reset the values
			star.s[j] = random(1, 10);
			star.x[j] = random(-20, 0-star.s[j]); //HOWEVER, I reset the values with the X position offscreen, so there appears to be a continuous scroll
			star.y[j] = random(0, height);
    	    star.dx[j] = star.s[j] / 200;
		}else{
			star.x[j] += star.dx[j]; //if star is not offscreen, it moves to the right
		}
	}
}

function planetUpdate(){
	for(var i = 0; i < numPlanets; i++){ 
		if(d[i] <= 1){ //selects planet type: if d is less than/equal to one, planet A is drawn, if d is greater than one, planet B is drawn
			drawPlanetA(planet.x[i], planet.y[i], planet.s[i], i);
		}else if(d[i] > 1){
			drawPlanetB(planet.x[i], planet.y[i], planet.s[i], i);
		}

		if(planet.x[i] >= width + planet.s[i] + (planet.s[i] * (2/3))){ //if planet has fully moved off screen, I reset the values
			planet.s[i] = random(10, 150);
			planet.x[i] = random(-200, 0-planet.s[i]); //HOWEVER, I reset the values with the X position offscreen, so there appears to be a continuous scroll
			planet.y[i] = random(0, height);
    	    planet.r[i] = random(20, 235);
    	    planet.g[i] = random(20, 235);
    	    planet.b[i] = random(20, 235);
    	    planet.dx[i] = planet.s[i] / 200;
		}else{
			planet.x[i] += planet.dx[i]; //if planet is not offscreen, it moves to the right
		}
	}
}

function astroUpdate(){
	for(var k = 0; k < 3; k++){
		image(astroPics[k], astro.x[k], astro.y[k], astro.s[k], astro.s[k]);
		if(astro.x[k] >= astro.e[k]){
			astro.x[k] = random(-2000, -150);
			astro.y[k] = random(0, height);
			astro.s[k] = random(30, 400);
			astro.dx[k] = astro.s[k] / 200;
			astro.e[k] = random(height+150, 2000);
		}else{
			astro.x[k] += astro.dx[k];
		}
	}
}

function planetInitialize(){
	for(var i = 0; i < numPlanets; i++){
    	planet.x[i] = random(0, width); //x position
    	planet.y[i] = random(0, height); //y position
    	planet.s[i] = random(10, 150); //size
    	planet.r[i] = random(20, 235); //r, g, and b are randomized. I seperated these instead of creating a color variable so I could use R, G, and B to edit the details
    	planet.g[i] = random(20, 235);
    	planet.b[i] = random(20, 235);
    	planet.dx[i] = planet.s[i] / 200; //dx is related to the size of the planet, if it's bigger it will appear to move quicker
    	d[i] = (random(0, 2)); //variable d selects whether or not planet type A or B is selected
    }
}

function starInitialize(){
	for(var j = 0; j < numStars; j++){
    	star.x[j] = random(0, width);
    	star.y[j] = random(0, height);
    	star.s[j] = random(1, 10);
    	star.dx[j] = star.s[j] / 200; //dx is related to the size of the star, if it's bigger it will appear to move quicker
    }
}

function astroInitialize(){
	for(var k = 0; k < 3; k++){
    	astro.x[k] = random(-2000, width)
    	astro.y[k] = random(0, height);
    	astro.s[k] = random(30, 150);
    	astro.dx[k] = astro.s[k] / 200; 
    	astro.e[k] = random(height+150, 2000); //astro end: beginning/end determines where image starts/ends it's journey before reset. I made the value larger so there would be greater diversity in when astronaunts appeared
    }
}

Looking Outwards 11

NFTs Are Shaking Up the Art World—But They Could Change So Much More

https://time.com/5947720/nft-art/ 

This article discusses the ways in which the art world could be altered via the growing popularity of NFTs (non-fungible tokens). It discusses many advantages, specifically positioning the creators of NFTs as down-on-their luck digital artists posed to receive notable benefits. These benefits include an increased ability to profit from one’s art, alongside the means to make one’s digital art pieces more exclusive, and hence, considered more valuable. This, however, completely neglects to mention the ways NFTs are actually used, alongside the culture surrounding them. NFTs are not bought because someone likes the art, or at the very least, that is not the primary reason for buying them. People buy NFTs to grow their own wealth at a gamble, and it’s safe to say that the already wealthy are not those who could lose the most from investing. Those who possess social capital (think CEOs, billionaires, celebrities) are easily able to construct their own NFTs and profit hugely, the reality being that very few digital artists are, in actuality, gaining financial stability from the practice, as the article implies. Like other assets on the blockchain, it would be ridiculous to pretend that NFTs don’t serve as a tool to further enrich the wealthy, usually at the expense of those outside of the 1%. Especially given the state of capitalism in this country, this is, without a doubt, extremely damaging. Though mentioned in the article, it is also worth re-acknowledging the fact that NFTs (and anything else on the blockchain) are bad for the environment, the computer clusters used to farm NFTs often powered by fossil fuels. This article is definitely biased in favor of NFTs, and perhaps unfairly fails to mention the realities of them. That being said, the title is right: NFTs could change so much more than the art world- change it for the worse.

Looking Outward 11 – Racial Biases in Artificial Intelligence

In this article, Meilan Solly discusses a project (ImageNet Roulette) by Trevor Paglen and Kate Crawford that was created to expose the highly flawed and derogatory nature of AI human categorization. The project in question took the form of an AI driven identification tool that, when supplied with an image of a person, would return the category to which that image belongs (according to the algorithm). Categories or identifiers ranged on a spectrum of neutral to problematic terms like ‘pervert’, ‘alky (alcoholic)’, and ‘slut’.

While the category names are disturbing in and of themselves, the trends of categorization were far more so. Generally, the algorithm would sort people of color and women into extremely offensive categories at a disproportionately high rate. While no type of person was entirely safe from a harmful identifier, the disparity was clear. Solly describes a trial of the algorithm by a twitter user who uploaded photos of himself in various contexts and was only returned the tags “Black, Black African, Negroid, and Negro” (Solly). Paglen and Crawford have since removed ImageNet Roulette from the internet given that it has “made it’s point” (Solly), however it is still available as an art installation in Milan.

7-Training-Humans-24.jpg
ImageNet Roulette Installation

The implications of this project run deep. Arbitrary categorization of people on its own may have little consequence, but the underlying system to which it alludes is the same system that functions in the background of active AI processes with real world applications. Beyond this, the project makes comments on the concept of privacy online, having used thousands of images sourced from various locations without consent.

Looking Outwards 11

The societal issue that was mentioned in the reading talked about how shows art projects show racial prejudice through artificial intelligence both directly and indirectly. One specific example that stood out was the “ImageNet Roulette”. It is an artificial intelligence classification tool created by artist Trevor Paglen and A.I. researcher Kate Crawford. The AI would give the person it detects in the picture a title. Sometimes it’s objective, like a career but most of the time it judges based on skin color and it gives out subjective descriptions. It was an issue because the labels used to teach A.I. were sourced from the lab staff and crowdsourced workers; by categorizing presented images in terms of race, gender, age, and character, these individuals introduced their own conscious and unconscious opinions and biases into the algorithm. Something I’ve noticed is that for artwork that requires testing artists, there often is a neglecting representation of different racial groups. Being a minority, I often get disappointed to see my group not being represented in those works.

The physical AI art installation at Milan’s Fondazione Prada Osservertario

Citation:
Magazine, S. (2019, September 24). Art project shows racial biases in artificial intelligence system. Smithsonian.com. Retrieved November 16, 2022, from https://www.smithsonianmag.com/smart-news/art-project-exposed-racial-biases-artificial-intelligence-system-180973207/

LO-11: How New Media Artists Bridge the Digital Divide

In “How Artists Can Bridge the Digital Divide and Reimagine Humanity,” Chavez addresses the importance of the role that new media artists play in closing the “digital divide” – that is, equipping people around the world with the necessary knowledge as well as skills to move from simply being consumers of digital media and content to being producers of it. As outlined by Chavez, the steps to achieve this goal are as follows: 

Closing the initial gap of access to digital technologies;

Harnessing wonder through creating fun, engaging projects that facilitate interest in participating in a new, digital society;

Creating shareable digital resources, otherwise known as public goods;

Addressing the STEMarts Model.

As it currently stands, an elite minority – those with proper access to new media technologies and the necessary skills to manipulate them – are responsible for creating the vast majority of new digital media content online. In bridging the gap between art and STEM, we expand our understanding of ourselves, our humanity, and our roles in society; as Chavez outlines in her article, by supporting artists who innovate by creating new digital tools and experiences, we encourage diverse communities across the globe to participate in the reimagination of humanity.

https://www.arts.gov/impact/media-arts/arts-technology-scan/essays/how-artists-can-bridge-digital-divide-and-reimagine-humanity

srauch – Blog 11 – Societal Impacts of Digital Art

I found a very interesting episode of Sidedoor, a podcast created by the Smithsonian, that interviewed artist Stephanie Dinkins about her work on how Black stories interact with AI.

Many AIs that are programmed to generate language pull information from the internet. This makes sense – if you’re looking to train an AI to talk, why not use the biggest and most easily accessible database of language in the world? Well, because, as Dinkins articulates, the internet is racist. It’s full of language that, even if it’s not overtly racist, is filled with the inherent racist biases and assumptions that have become ingrained within the English language. Those biases, by extension, become embedded in the AI. To counter this phenomena, Dinkins created Not the Only One: an AI that creates a memoir of a Black American family. It draws its language ability not from the internet, but from the familial stories from Dinkins, her mother, and her grandmother. Her work raises valuable questions about where our information is coming from. While we think of computers as completely logical, we can’t forget that they’re a product of human creation, and thus always susceptible to our biases and human errors.

Project 10: Sonic Story

Nick’s Prank (Story inspired by Zootopia Teaser Trailer)

Judy the bunny and the goat are walking on the street. Nick the fox sees them and decides to play a prank on Judy. When Judy passes Nick, Nick puts out his foot and trips Judy. In a panic, Judy pushes the goat walking in front of her, so the goat falls down as well. After seeing them both fall, Nick hums with joy.

sketch
//Xinyi Du 
//15104 Section B
//xinyidu@andrew.cmu.edu
//Project-10

//Nick's Prank (Story inspired by Zootopia Teaser Trailer)

//Judy the bunny and the goat are walking on the street. 
//Nick the fox sees them and decides to play a prank on Judy.
//When Judy passes Nick, Nick puts out his foot and trips Judy.
//In panic, judy pushes the goat walking in front of her, so the goat falls down as well.
//After seeing them both fall, Nick hums with joy.

/* 
Images of characters from Zootopia Teaser Trailer:
https://www.youtube.com/watch?v=g9lmhBYB11U

Street image source: 
https://www.etsy.com/au/listing/581765202/the-buildings-of-main-street-walt-disney?
ref=related-2&epik=dj0yJnU9UWhoMkVRQnRMc1hFbk40dXRWQ21FVUdSVG9iYVFZT3QmcD0wJm49RWRs
YUhPc25aWUxvdTY5ZEtod3liQSZ0PUFBQUFBR053QWdv
*/


var filenames = [];
var walkImage = []; //walk cycle images of judy

var filenames2 = [];
var fallImage = []; //fall images of judy

var filenames3 = [];
var walkImage2 = []; //walk cycle images of the goat

var filenames4 = [];
var fallImage2 = []; //fall images of the goat

var character = [];
var street;
var clouds;
var nick;

var walk; //walking footsteps sound variable
var ouch; //ouch sound judy makes when fall
var bodyfall; //body falling sound of the goat
var nickhumming; //happy humming of nick

function preload(){
    //load sounds
    walk = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/footsteps.mp3");
    ouch = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/ouch.mp3");
    bodyfall = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/bodyfall.wav");
    nickhumming = loadSound("https://courses.ideate.cmu.edu/15-104/f2022/wp-content/uploads/2022/11/happy-huming.mp3");
    
    //load images
    //walk cycle images of judy
    filenames[0] = "https://i.imgur.com/wLVmUpf.png";
    filenames[1] = "https://i.imgur.com/TffffQ8.png";
    filenames[2] = "https://i.imgur.com/5Lirbd1.png";
    filenames[3] = "https://i.imgur.com/N2BUn7y.png";
    filenames[4] = "https://i.imgur.com/pc6Lp46.png";
    filenames[5] = "https://i.imgur.com/lhOcePN.png";
    filenames[6] = "https://i.imgur.com/djXrWqQ.png";
    filenames[7] = "https://i.imgur.com/8nXGJZe.png";
    filenames[8] = "https://i.imgur.com/D8o0eOa.png";
    filenames[9] = "https://i.imgur.com/qzJQm37.png";
    for (var i = 0; i < filenames.length; i++) {
        walkImage[i] = loadImage(filenames[i]);
    }
    //fall images of judy
    filenames2[0] = "https://i.imgur.com/c1vUye5.png";
    filenames2[1] = "https://i.imgur.com/mbibpsr.png";
    filenames2[2] = "https://i.imgur.com/ZSeL7on.png";
    filenames2[3] = "https://i.imgur.com/UNqmLD7.png";
    for (var i = 0; i < filenames2.length; i++) {
        fallImage[i] = loadImage(filenames2[i]);
    }
    //walk cycle images of the goat
    filenames3[0] = "https://i.imgur.com/RRf37Kf.png";
    filenames3[1] = "https://i.imgur.com/ue4D3ig.png";
    filenames3[2] = "https://i.imgur.com/MxIlCqf.png";
    filenames3[3] = "https://i.imgur.com/UDHWsZ8.png";
    filenames3[4] = "https://i.imgur.com/a3nmvz3.png";
    filenames3[5] = "https://i.imgur.com/i75T56A.png";
    filenames3[6] = "https://i.imgur.com/cN4M52I.png";
    filenames3[7] = "https://i.imgur.com/A1iDTIi.png";
    for (var i = 0; i < filenames3.length; i++) {
        walkImage2[i] = loadImage(filenames3[i]);
    }
    //fall images of the goat
    filenames4[0] = "https://i.imgur.com/plfUZHK.png";
    filenames4[1] = "https://i.imgur.com/g7C3kXU.png";
    filenames4[2] = "https://i.imgur.com/14PuZpL.png";
    filenames4[3] = "https://i.imgur.com/Pcl7xcg.png";
    filenames4[4] = "https://i.imgur.com/KC56zzH.png";
    for (var i = 0; i < filenames4.length; i++) {
        fallImage2[i] = loadImage(filenames4[i]);
    }

    street = loadImage("https://i.imgur.com/G0SJIDN.jpg");
    clouds = loadImage("https://i.imgur.com/LbxT2nS.png");
    nick = loadImage("https://i.imgur.com/hEIvnaB.png");
}

//constructor for walking judy
function makeJudy(jx, jy, jdx) {
    var j = {x: jx, y: jy, dx: jdx,
             imageNum: 0,
             stepFunction: stepJudy,
             drawFunction: drawJudy
         }
    return j;
}
function stepJudy() {
    this.x += this.dx; //increase x by dx
    this.imageNum ++; //increase imageNum
    //if reaches the length (end) of the array (go over 10 images), start from 0 again
    if (this.imageNum == walkImage.length) { 
        this.imageNum = 0;
    }
}
function drawJudy() {
    image(walkImage[this.imageNum], this.x, this.y, 63, 80); //draw the image
}


//constructor for falling judy
function makeFallDown(fx, fy) {
    var f = {x: fx, y: fy, imageNum: 0,
            stepFunction: stepFallDown,
            drawFunction: drawFallDown
         }
    return f;
}
function stepFallDown() {
    //increases imageNum only when it has not exceed the length of the array fallImage
    if(this.imageNum < fallImage.length-1) {
        this.imageNum ++;
    }  
}
function drawFallDown() {
    image(fallImage[this.imageNum], this.x, this.y, 170, 100);
}


//constructor for walking goat
function makeNewChar(cx, cy, cdx) {
    var c = {x: cx, y: cy, dx: cdx,
             imageNum: 0,
             stepFunction: stepChar,
             drawFunction: drawChar
         }
    return c;
}
function stepChar() {
    this.x += this.dx; 
    this.imageNum ++; 
    if (this.imageNum == walkImage2.length) { 
        this.imageNum = 0;
    }
}
function drawChar() {
    image(walkImage2[this.imageNum], this.x, this.y, 120, 180); 
}


//constructor for falling goat
function makeFallDown2(fx, fy) {
    var f = {x: fx, y: fy, imageNum: 0,
            stepFunction: stepFallDown2,
            drawFunction: drawFallDown2
         }
    return f;
}
function stepFallDown2() {
    if(this.imageNum < fallImage2.length-1) {
        this.imageNum ++; 
    }  
}
function drawFallDown2() {
    image(fallImage2[this.imageNum], this.x, this.y, 300, 200);
}

//set up sounds
function soundSetup() {
    walk.setVolume(0.4);
    ouch.setVolume(0.8);
    bodyfall.setVolume(1.2);
    nickhumming.setVolume(0.1);
}
//define a function to add the sounds
function addSounds() {
    if(frameCount % 15 == 1) {
        walk.play(); //walking footstep sounds very 15 frameCounts
    }
    if(frameCount == 99) {
        ouch.play(); //judy makes "ouch" sound when being tripped
    }
    if(frameCount > 100){
        walk.stop(); //stop walking footstep sounds when falling down
    }
    if(frameCount == 100) {
        bodyfall.play(); //body falling sound of the goat after judy falls
    }
    if(frameCount == 108) {
        nickhumming.play(); //nick humming after they both falls
        noLoop(); //end the loop
    }
}



function setup() {
    createCanvas(700, 500);
    frameRate(5);
    useSound();
    //store the characters info to the characters array
    var judyX = width/4;
    character.push(makeJudy(judyX, height-94, 0));
    character.push(makeFallDown(judyX, height-112, 0));
    var newCharX = width/3;
    character.push(makeNewChar(newCharX, height-184, 0)); //walking goat before judy falls
    var newChar2X = width/3;
    character.push(makeNewChar(newChar2X, height-184, 10)); //goat after judy falls, continue walking
    character.push(makeFallDown2(290, height-199, 10));
}

function draw() {
    background(25);
    //call the addSounds function to add sounds
    addSounds();
    //constrain the Xs of the images of street and clouds so that they stop rolling when Judy falls
    //street and clouds rolling with different speed according to frameCount
    var streetX = constrain(0-frameCount*10, -1000, 0); 
    var cloudsX = constrain(0-frameCount*5, -500, 0);
    image(street, streetX, -70, 2000, 600);
    image(clouds, cloudsX, -100, 2000, 600);

    //update the steps and draw the characters
    //constrain the X of nick so that it does not move when the street scene stops
    var nickX = constrain(1175-frameCount*10, 175, 1000);
    var judyX = width/4;
    var newCharX = width/11;
    //if judy (width/4) has not meet nick(nickX)
    if (nickX > width/4) {
        //draw the image of nick
        image(nick, nickX, height-111, 80, 100);
        character[2].stepFunction(); 
        character[2].drawFunction(); //walking goat
        character[0].stepFunction();
        character[0].drawFunction(); //walking judy
    } 
    //if judy (width/4) passes by nick(nickX)
    if (judyX == nickX) {
        character[1].stepFunction();
        character[1].drawFunction(); //judy falls down
        //the goat continue walking
        if (character[3].x < 250) { 
            character[3].stepFunction();
            character[3].drawFunction(); //walking goat
        }
    } 
    //if judy pushes the goat
    if (character[3].x >= 250) {
        character[4].stepFunction();
        character[4].drawFunction(); //goat falls down
    }
}