图像和像素(Images and Pixels)
圖像和像素
數(shù)字圖像只不過(guò)是數(shù)據(jù)——數(shù)字表示像素網(wǎng)格上特定位置的紅色、綠色和藍(lán)色的變化。大多數(shù)時(shí)候,我們將這些像素視為夾在計(jì)算機(jī)屏幕上的微型矩形。然而,通過(guò)一些創(chuàng)造性的思考和使用代碼對(duì)像素進(jìn)行一些較低級(jí)別的操作,我們可以以多種方式顯示該信息。本教程致力于打破處理中的簡(jiǎn)單形狀繪制,并使用圖像(及其像素)作為處理圖形的構(gòu)建塊。
圖像入門。
希望您對(duì)數(shù)據(jù)類型的概念感到滿意。您可能經(jīng)常指定它們——浮點(diǎn)變量“速度”、整數(shù)“x”等。這些都是原始數(shù)據(jù)類型,位于計(jì)算機(jī)內(nèi)存中的位可供我們使用。雖然可能有點(diǎn)棘手,但您希望也可以使用對(duì)象、存儲(chǔ)多條數(shù)據(jù)(以及功能)的復(fù)雜數(shù)據(jù)類型——例如,“Ball”類可能包括位置、大小和速度的浮點(diǎn)變量作為移動(dòng)、顯示自身等的方法。
除了用戶定義的對(duì)象(例如 Ball)之外,Processing 還有一堆方便的類,無(wú)需我們編寫任何代碼即可使用。在本教程中,我們將研究PImage,這是一個(gè)用于加載和顯示圖像以及查看其像素的類。
PImage img; // Declare a variable of type PImagevoid setup() {size(320,240);// Make a new instance of a PImage by loading an image fileimg = loadImage("mysummervacation.jpg"); }void draw() {background(0);// Draw the image to the screen at coordinate (0,0)image(img,0,0); }使用PImage對(duì)象的實(shí)例與使用用戶定義的類沒(méi)有什么不同。首先,聲明了一個(gè)名為“img”的PImage類型的變量。其次,通過(guò)loadImage()方法創(chuàng)建PImage對(duì)象的新實(shí)例。loadImage()接受一個(gè)參數(shù),a指示文件名,并將該文件加載到內(nèi)存中。loadImage()查找存儲(chǔ)在處理草圖的“數(shù)據(jù)”文件夾中的圖像文件。String
數(shù)據(jù)文件夾:我如何到達(dá)那里?
圖像可以通過(guò)以下方式自動(dòng)添加到數(shù)據(jù)文件夾:
草圖→添加文件。. .
或手動(dòng):
草圖→顯示草圖文件夾
這將打開(kāi)草圖文件夾。如果沒(méi)有數(shù)據(jù)目錄創(chuàng)建一個(gè)。否則,將您的圖像文件放入其中。
Processing 接受以下圖像文件格式:GIF、JPG、TGA、PNG。
在上面的示例中,我們從未調(diào)用“構(gòu)造函數(shù)”來(lái)實(shí)例化PImage對(duì)象,這似乎有點(diǎn)奇怪,比如new PImage(). 畢竟,在大多數(shù)與對(duì)象相關(guān)的示例中,構(gòu)造函數(shù)是生成對(duì)象實(shí)例所必需的。
Spaceship ss = new Spaceship(); Flower flr = new Flower(25);然而:
PImage img = loadImage("file.jpg");實(shí)際上,loadImage()函數(shù)執(zhí)行構(gòu)造函數(shù)的工作,返回從指定文件名生成的PImage對(duì)象的全新實(shí)例。我們可以將其視為用于從文件加載圖像的PImage構(gòu)造函數(shù)。為了創(chuàng)建空白圖像,使用createImage()函數(shù)。
// Create a blank image, 200 x 200 pixels with RGB color PImage img = createImage(200, 200,RGB);我們還應(yīng)該注意,將圖像從硬盤加載到內(nèi)存的過(guò)程是一個(gè)緩慢的過(guò)程,我們應(yīng)該確保我們的程序只需要執(zhí)行一次,在setup(). 加載圖像draw()可能會(huì)導(dǎo)致性能下降以及“內(nèi)存不足”錯(cuò)誤。
加載圖像后,將使用image()函數(shù)顯示它。image()函數(shù)必須包含 3 個(gè)參數(shù)——要顯示的圖像、x 位置和 y 位置??梢赃x擇添加兩個(gè)參數(shù)來(lái)將圖像調(diào)整為特定的寬度和高度。
image(img,10,20,90,60);您的第一個(gè)圖像處理濾鏡
顯示圖像時(shí),您可能希望更改其外觀。也許您希望圖像看起來(lái)更暗、透明、偏藍(lán)等。這種簡(jiǎn)單的圖像過(guò)濾是通過(guò) Processing 的tint()函數(shù)實(shí)現(xiàn)的。tint()本質(zhì)上是 shape 的圖像等價(jià)物fill(),設(shè)置在屏幕上顯示圖像的顏色和 alpha 透明度。然而,圖像通常并不都是一種顏色。的參數(shù)tint()僅指定該圖像的每個(gè)像素使用多少給定顏色,以及這些像素應(yīng)該顯示的透明程度。
對(duì)于以下示例,我們將假設(shè)已加載兩個(gè)圖像(向日葵和狗),并且將狗顯示為背景(這將允許我們展示透明度。)
PImage sunflower = loadImage("sunflower.jpg"); PImage dog = loadImage("dog.jpg"); background(dog);如果tint()接收一個(gè)參數(shù),則僅影響圖像的亮度。
// The image retains its original state. tint(255); image(sunflower,0,0); // The image appears darker. tint(100); image(sunflower,0,0);第二個(gè)參數(shù)將改變圖像的 alpha 透明度。
// The image is at 50% opacity. tint(255,127); image(sunflower,0,0);三個(gè)參數(shù)影響每種顏色的紅色、綠色和藍(lán)色分量的亮度。
// None of its red, most of its green, and all of its blue. tint(0,200,255); image(sunflower,0,0);最后,向該方法添加第四個(gè)參數(shù)來(lái)操作 alpha(與 2 相同)。tint()順便說(shuō)一句,可以使用colorMode()指定值的范圍。
// The image is tinted red and transparent. tint(255,0,0,100); image(sunflower,0,0);像素、像素和更多像素
如果您剛剛開(kāi)始使用 Processing,您可能會(huì)錯(cuò)誤地認(rèn)為唯一提供的用于繪制到屏幕的方法是通過(guò)函數(shù)調(diào)用。“在這些點(diǎn)之間畫一條線”或“用紅色填充橢圓”或“加載此 JPG 圖像并將其放置在此處的屏幕上”。但不知何故,有人不得不編寫代碼,將這些函數(shù)調(diào)用轉(zhuǎn)換為設(shè)置屏幕上的各個(gè)像素以反映所請(qǐng)求的形狀。一條線沒(méi)有出現(xiàn)是因?yàn)槲覀冋f(shuō)line(),它出現(xiàn)是因?yàn)槲覀優(yōu)閮牲c(diǎn)之間的線性路徑上的所有像素著色。幸運(yùn)的是,我們不必每天管理這種較低級(jí)別的像素設(shè)置。我們要感謝 Processing(和 Java)的開(kāi)發(fā)人員,感謝他們處理這項(xiàng)業(yè)務(wù)的許多繪圖功能。
盡管如此,我們還是時(shí)不時(shí)想要打破我們世俗的圖形繪制存在,直接處理屏幕上的像素。處理通過(guò)像素陣列提供此功能。
我們熟悉屏幕上的每個(gè)像素在二維窗口中都有一個(gè) X 和 Y 位置的想法。然而,陣列像素只有一維,以線性順序存儲(chǔ)顏色值。
舉個(gè)簡(jiǎn)單的例子。該程序?qū)⒋翱谥械拿總€(gè)像素設(shè)置為隨機(jī)灰度值。像素?cái)?shù)組就像其他數(shù)組一樣,唯一的區(qū)別是我們不必聲明它,因?yàn)樗且粋€(gè)處理內(nèi)置變量。
示例:設(shè)置像素
size(200, 200); // Before we deal with pixels loadPixels(); // Loop through every pixel for (int i = 0; i < pixels.length; i++) {// Pick a random number, 0 to 255float rand = random(255);// Create a grayscale color based on random numbercolor c = color(rand);// Set pixel at that location to random colorpixels[i] = c; } // When we are finished dealing with pixels updatePixels();首先,我們應(yīng)該在上面的例子中指出一些重要的東西。每當(dāng)您訪問(wèn)處理窗口的像素時(shí),您必須提醒處理此活動(dòng)。這是通過(guò)兩個(gè)功能完成的:
- loadPixels()這個(gè)函數(shù)在你訪問(wèn)像素?cái)?shù)組之前被調(diào)用,說(shuō)“加載像素,我想和他們說(shuō)話!”
- updatePixels()這個(gè)函數(shù)在你完成像素?cái)?shù)組后調(diào)用,“繼續(xù)更新像素,我已經(jīng)完成了!”
在上面的例子中,因?yàn)轭伾请S機(jī)設(shè)置的,所以我們不必?fù)?dān)心像素在屏幕上的位置,因?yàn)槲覀冎皇窃O(shè)置了所有像素,而不考慮它們的相對(duì)位置。然而,在許多圖像處理應(yīng)用中,像素本身的 XY 位置是至關(guān)重要的信息。一個(gè)簡(jiǎn)單的示例可能是將每個(gè)偶數(shù)列像素設(shè)置為白色,將每個(gè)奇數(shù)列設(shè)置為黑色。你怎么能用一維像素陣列做到這一點(diǎn)?你怎么知道任何給定像素在哪一列或哪一行?
在使用像素進(jìn)行編程時(shí),我們需要能夠?qū)⒚總€(gè)像素視為生活在二維世界中,但要繼續(xù)訪問(wèn)一個(gè)二維世界中的數(shù)據(jù)(因?yàn)檫@就是我們可以使用它的方式)。我們可以通過(guò)以下公式做到這一點(diǎn):
這可能會(huì)讓您想起我們的二維數(shù)組教程。事實(shí)上,我們需要使用相同的嵌套 for 循環(huán)技術(shù)。不同之處在于,雖然我們想使用 for 循環(huán)來(lái)考慮二維像素,但當(dāng)我們實(shí)際訪問(wèn)像素時(shí),它們存在于一維數(shù)組中,我們必須應(yīng)用上圖中的公式。
讓我們看看它是如何完成的。
示例:根據(jù) 2D 位置設(shè)置像素
size(200, 200); loadPixels(); // Loop through every pixel column for (int x = 0; x < width; x++) {// Loop through every pixel rowfor (int y = 0; y < height; y++) {// Use the formula to find the 1D locationint loc = x + y * width;if (x % 2 == 0) { // If we are an even columnpixels[loc] = color(255);} else { // If we are an odd columnpixels[loc] = color(0);}} } updatePixels();圖像處理簡(jiǎn)介
上一節(jié)介紹了根據(jù)任意計(jì)算設(shè)置像素值的示例。我們現(xiàn)在將看看如何根據(jù)現(xiàn)有PImage對(duì)象中的像素設(shè)置像素。這是一些偽代碼。
將圖像文件加載到 PImage 對(duì)象中
對(duì)于 PImage 中的每個(gè)像素,檢索像素的顏色并將顯示像素設(shè)置為該顏色。
PImage類包括一些有用的字段,用于存儲(chǔ)與圖像相關(guān)的數(shù)據(jù)——寬度、高度和像素。就像我們的用戶定義的類一樣,我們可以通過(guò)點(diǎn)語(yǔ)法訪問(wèn)這些字段。
PImage img = createImage(320,240,RGB); // Make a PImage object
println(img.width); // Yields 320
println(img.height); // Yields 240
img.pixels[0] = color(255,0,0); // Sets the first pixel of the image to red
訪問(wèn)這些字段使我們能夠遍歷圖像的所有像素并將它們顯示在屏幕上。
示例:顯示圖像的像素
PImage img;void setup() {size(200, 200);img = loadImage("sunflower.jpg"); }void draw() {loadPixels();// Since we are going to access the image's pixels tooimg.loadPixels();for (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {int loc = x + y*width;// The functions red(), green(), and blue() pull out the 3 color components from a pixel.float r = red(img.pixels[loc]);float g = green(img.pixels[loc]);float b = blue(img.pixels[loc]);// Image Processing would go here// If we were to change the RGB values, we would do it here,// before setting the pixel in the display window.// Set the display pixel to the image pixelpixels[loc] = color(r,g,b);}}updatePixels(); }現(xiàn)在,我們當(dāng)然可以進(jìn)行簡(jiǎn)化以僅顯示圖像(例如,不需要嵌套循環(huán),更不用說(shuō)使用image()函數(shù)將允許我們完全跳過(guò)所有這些像素工作。)但是,示例 15-7 提供了一個(gè)基本框架,用于根據(jù)每個(gè)像素的空間方向(XY 位置)獲取每個(gè)像素的紅色、綠色和藍(lán)色值;最終,這將使我們能夠開(kāi)發(fā)更先進(jìn)的圖像處理算法。
在我們繼續(xù)之前,我應(yīng)該強(qiáng)調(diào)這個(gè)例子是有效的,因?yàn)轱@示區(qū)域與源圖像具有相同的尺寸。如果不是這種情況,您只需計(jì)算兩個(gè)像素位置,一個(gè)用于源圖像,一個(gè)用于顯示區(qū)域。
int imageLoc = x + y*img.width; int displayLoc = x + y*width;我們的第二個(gè)圖像過(guò)濾器,制作我們自己的“色調(diào)”
就在幾段前,我們正在享受輕松的編碼會(huì)議,使用友好的tint()方法為圖像著色并添加 alpha 透明度。對(duì)于基本過(guò)濾,這種方法可以解決問(wèn)題。然而,逐像素方法將允許我們開(kāi)發(fā)自定義算法,以數(shù)學(xué)方式改變圖像的顏色。考慮亮度-較亮的顏色具有較高的紅色、綠色和藍(lán)色分量值。很自然地,我們可以通過(guò)增加或減少每個(gè)像素的顏色分量來(lái)改變圖像的亮度。在下一個(gè)示例中,我們根據(jù)鼠標(biāo)的水平位置動(dòng)態(tài)地增加或減少這些值。(注意,接下來(lái)的兩個(gè)示例僅包括圖像處理循環(huán)本身,其余代碼是假定的。)
示例:調(diào)整圖像亮度
for (int x = 0; x < img.width; x++) {for (int y = 0; y < img.height; y++ ) {// Calculate the 1D pixel locationint loc = x + y*img.width;// Get the R,G,B values from imagefloat r = red (img.pixels[loc]);float g = green (img.pixels[loc]);float b = blue (img.pixels[loc]);// Change brightness according to the mouse herefloat adjustBrightness = ((float) mouseX / width) * 8.0;r *= adjustBrightness;g *= adjustBrightness;b *= adjustBrightness;// Constrain RGB to between 0-255r = constrain(r,0,255);g = constrain(g,0,255);b = constrain(b,0,255);// Make a new color and set pixel in the windowcolor c = color(r,g,b);pixels[loc] = c;} }由于我們是在每個(gè)像素的基礎(chǔ)上更改圖像,因此不需要平等對(duì)待所有像素。例如,我們可以根據(jù)每個(gè)像素與鼠標(biāo)的距離來(lái)改變每個(gè)像素的亮度。
示例:根據(jù)像素位置調(diào)整圖像亮度
for (int x = 0; x < img.width; x++) {for (int y = 0; y < img.height; y++ ) {// Calculate the 1D pixel locationint loc = x + y*img.width;// Get the R,G,B values from imagefloat r = red (img.pixels[loc]);float g = green (img.pixels[loc]);float b = blue (img.pixels[loc]);// Calculate an amount to change brightness// based on proximity to the mousefloat distance = dist(x,y,mouseX,mouseY);float adjustBrightness = (50-distance)/50;r *= adjustBrightness;g *= adjustBrightness;b *= adjustBrightness;// Constrain RGB to between 0-255r = constrain(r,0,255);g = constrain(g,0,255);b = constrain(b,0,255);// Make a new color and set pixel in the windowcolor c = color(r,g,b);pixels[loc] = c;} }寫入另一個(gè) PImage 對(duì)象的像素
我們所有的圖像處理示例都從源圖像中讀取了每個(gè)像素,并將一個(gè)新像素直接寫入處理窗口。但是,將新像素寫入目標(biāo)圖像(然后使用image()函數(shù)顯示)通常更方便。我們將在查看另一個(gè)簡(jiǎn)單的像素操作時(shí)演示此技術(shù):閾值。
閾值過(guò)濾器僅以兩種狀態(tài)(黑色或白色)中的一種顯示圖像的每個(gè)像素。該狀態(tài)是根據(jù)特定閾值設(shè)置的。如果像素的亮度大于閾值,我們將像素著色為白色,小于,黑色。在下面的代碼中,我們使用任意閾值 100。
示例:亮度閾值
PImage source; // Source image PImage destination; // Destination imagevoid setup() {size(200, 200);source = loadImage("sunflower.jpg");// The destination image is created as a blank image the same size as the source.destination = createImage(source.width, source.height, RGB); }void draw() {float threshold = 127;// We are going to look at both image's pixelssource.loadPixels();destination.loadPixels();for (int x = 0; x < source.width; x++) {for (int y = 0; y < source.height; y++ ) {int loc = x + y*source.width;// Test the brightness against the thresholdif (brightness(source.pixels[loc]) > threshold) {destination.pixels[loc] = color(255); // White} else {destination.pixels[loc] = color(0); // Black}}}// We changed the pixels in destinationdestination.updatePixels();// Display the destinationimage(destination,0,0); }作為 Processing 的filter()函數(shù)的一部分,此特定功能無(wú)需按像素處理即可使用。但是,如果您想實(shí)現(xiàn)自己的圖像處理算法,了解較低級(jí)別的代碼至關(guān)重要,而filter().
但是,如果您想要做的只是閾值,那么方法如下:
// Draw the image image(img,0,0); // Filter the window with a threshold effect // 0.5 means threshold is 50% brightness filter(THRESHOLD,0.5);二級(jí):像素組處理
在前面的示例中,我們已經(jīng)看到源像素和目標(biāo)像素之間存在一對(duì)一的關(guān)系。為了增加圖像的亮度,我們從源圖像中取出一個(gè)像素,增加 RGB 值,并在輸出窗口中顯示一個(gè)像素。為了執(zhí)行更高級(jí)的圖像處理功能,我們必須超越一對(duì)一的像素范式,進(jìn)入像素組處理。
讓我們從源圖像的兩個(gè)像素中創(chuàng)建一個(gè)新像素開(kāi)始——一個(gè)像素及其左側(cè)的鄰居。
如果我們知道像素位于 (x,y):
int loc = x + y*img.width; color pix = img.pixels[loc];然后它的左鄰居位于 (x-1,y):
int leftLoc = (x-1) + y*img.width; color leftPix = img.pixels[leftLoc];然后,我們可以根據(jù)像素與其左側(cè)相鄰像素之間的差異制作新顏色。
float diff = abs(brightness(pix) - brightness(leftPix)); pixels[loc] = color(diff);這是完整的算法:
示例:像素相鄰差異(邊緣)
// Since we are looking at left neighbors // We skip the first column for (int x = 1; x < width; x++) {for (int y = 0; y < height; y++ ) {// Pixel location and colorint loc = x + y*img.width;color pix = img.pixels[loc];// Pixel to the left location and colorint leftLoc = (x-1) + y*img.width;color leftPix = img.pixels[leftLoc];// New color is difference between pixel and left neighborfloat diff = abs(brightness(pix) - brightness(leftPix));pixels[loc] = color(diff);} }這個(gè)例子是一個(gè)簡(jiǎn)單的水平邊緣檢測(cè)算法。當(dāng)像素與其相鄰像素相差很大時(shí),它們很可能是“邊緣”像素。例如,想一想黑色桌面上的一張白紙圖片。那張紙的邊緣是顏色最不同的地方,白色與黑色的交匯處。
在前面的示例中,我們查看了兩個(gè)像素以查找邊緣。然而,更復(fù)雜的算法通常涉及一次查看多個(gè)像素。畢竟,每個(gè)像素都有 8 個(gè)直接鄰居:左上、上、右上、右、右下、下、左下、左。
這些圖像處理算法通常被稱為“空間卷積”。該過(guò)程使用輸入像素及其相鄰像素的加權(quán)平均值來(lái)計(jì)算輸出像素。換言之,該新像素是像素面積的函數(shù)??梢允褂貌煌笮〉南噜弲^(qū)域,例如 3x3 矩陣、5x5 等。
每個(gè)像素的不同權(quán)重組合會(huì)產(chǎn)生不同的效果。例如,我們通過(guò)減去相鄰像素值并增加中心點(diǎn)像素來(lái)“銳化”圖像。通過(guò)取所有相鄰像素的平均值來(lái)實(shí)現(xiàn)模糊。(請(qǐng)注意,卷積矩陣中的值加起來(lái)為 1)。
例如,
Sharpen: -1 -1 -1 -1 9 -1 -1 -1 -1Blur: 1/9 1/9 1/9 1/9 1/9 1/9 1/9 1/9 1/9下面是一個(gè)使用 2D 數(shù)組執(zhí)行卷積的示例(參見(jiàn)第 13 章,第 XX 頁(yè),回顧 2D 數(shù)組)來(lái)存儲(chǔ) 3x3 矩陣的像素權(quán)重。這個(gè)例子可能是迄今為止我們?cè)诒緯杏龅降淖罡呒?jí)的例子,因?yàn)樗婕昂芏嘣?#xff08;嵌套循環(huán)、2D 數(shù)組、PImage 像素等)。
示例:使用卷積銳化
PImage img; int w = 80;// It's possible to perform a convolution // the image with different matricesfloat[][] matrix = { { -1, -1, -1 },{ -1, 9, -1 },{ -1, -1, -1 } };void setup() {size(200, 200);frameRate(30);img = loadImage("sunflower.jpg"); }void draw() {// We're only going to process a portion of the image// so let's set the whole image as the background firstimage(img,0,0);// Where is the small rectangle we will processint xstart = constrain(mouseX-w/2,0,img.width);int ystart = constrain(mouseY-w/2,0,img.height);int xend = constrain(mouseX+w/2,0,img.width);int yend = constrain(mouseY+w/2,0,img.height);int matrixsize = 3;loadPixels();// Begin our loop for every pixelfor (int x = xstart; x < xend; x++) {for (int y = ystart; y < yend; y++ ) {// Each pixel location (x,y) gets passed into a function called convolution()// which returns a new color value to be displayed.color c = convolution(x,y,matrix,matrixsize,img);int loc = x + y*img.width;pixels[loc] = c;}}updatePixels();stroke(0);noFill();rect(xstart,ystart,w,w); }color convolution(int x, int y, float[][] matrix, int matrixsize, PImage img) {float rtotal = 0.0;float gtotal = 0.0;float btotal = 0.0;int offset = matrixsize / 2;// Loop through convolution matrixfor (int i = 0; i < matrixsize; i++){for (int j= 0; j < matrixsize; j++){// What pixel are we testingint xloc = x+i-offset;int yloc = y+j-offset;int loc = xloc + img.width*yloc;// Make sure we have not walked off the edge of the pixel arrayloc = constrain(loc,0,img.pixels.length-1);// Calculate the convolution// We sum all the neighboring pixels multiplied by the values in the convolution matrix.rtotal += (red(img.pixels[loc]) * matrix[i][j]);gtotal += (green(img.pixels[loc]) * matrix[i][j]);btotal += (blue(img.pixels[loc]) * matrix[i][j]);}}// Make sure RGB is within rangertotal = constrain(rtotal,0,255);gtotal = constrain(gtotal,0,255);btotal = constrain(btotal,0,255);// Return the resulting colorreturn color(rtotal,gtotal,btotal); }可視化圖像
你可能會(huì)想:“天哪,這一切都很有趣,但是說(shuō)真的,當(dāng)我想模糊圖像或改變它的亮度時(shí),我真的需要編寫代碼嗎?我的意思是,我不能使用 Photoshop 嗎?” 實(shí)際上,我們?cè)谶@里所取得的成果僅僅是對(duì) Adob??e 高技能程序員所做工作的初步了解。然而,Processing 的強(qiáng)大之處在于實(shí)時(shí)、交互式圖形應(yīng)用程序的潛力。我們沒(méi)有必要生活在“像素點(diǎn)”和“像素組”處理的范圍內(nèi)。
以下是繪制處理形狀的算法的兩個(gè)示例。我們不再像過(guò)去那樣隨機(jī)或使用硬編碼值對(duì)形狀進(jìn)行著色,而是從PImage對(duì)象內(nèi)部的像素中選擇顏色。圖像本身從不顯示;相反,它是一個(gè)信息數(shù)據(jù)庫(kù),我們可以利用它來(lái)進(jìn)行多種創(chuàng)造性的追求。
在第一個(gè)示例中,對(duì)于通過(guò) draw() 的每個(gè)循環(huán),我們?cè)谄聊簧系碾S機(jī)位置填充一個(gè)橢圓,顏色取自源圖像中對(duì)應(yīng)位置的顏色。結(jié)果是基本的“點(diǎn)畫式”效果:
示例:“點(diǎn)畫法”
PImage img; int pointillize = 16;void setup() {size(200,200);img = loadImage("sunflower.jpg");background(0);smooth(); }void draw() {// Pick a random pointint x = int(random(img.width));int y = int(random(img.height));int loc = x + y*img.width;// Look up the RGB color in the source imageloadPixels();float r = red(img.pixels[loc]);float g = green(img.pixels[loc]);float b = blue(img.pixels[loc]);noStroke();// Draw an ellipse at that location with that colorfill(r,g,b,100);ellipse(x,y,pointillize,pointillize); }在下一個(gè)示例中,我們從二維圖像中獲取數(shù)據(jù),并使用第 14 章中描述的 3D 平移技術(shù),為三維空間中的每個(gè)像素渲染一個(gè)矩形。z 位置由顏色的亮度決定。較亮的顏色看起來(lái)更靠近觀察者,而較暗的顏色則更遠(yuǎn)。
示例:2D 圖像映射到 3D
PImage img; // The source image int cellsize = 2; // Dimensions of each cell in the grid int cols, rows; // Number of columns and rows in our systemvoid setup() {size(200, 200, P3D);img = loadImage("sunflower.jpg"); // Load the imagecols = width/cellsize; // Calculate # of columnsrows = height/cellsize; // Calculate # of rows }void draw() {background(0);loadPixels();// Begin loop for columnsfor ( int i = 0; i < cols;i++) {// Begin loop for rowsfor ( int j = 0; j < rows;j++) {int x = i*cellsize + cellsize/2; // x positionint y = j*cellsize + cellsize/2; // y positionint loc = x + y*width; // Pixel array locationcolor c = img.pixels[loc]; // Grab the color// Calculate a z position as a function of mouseX and pixel brightnessfloat z = (mouseX/(float)width) * brightness(img.pixels[loc]) - 100.0;// Translate to the location, set fill and stroke, and draw the rectpushMatrix();translate(x,y,z);fill(c);noStroke();rectMode(CENTER);rect(0,0,cellsize,cellsize);popMatrix();}} }原文鏈接:https://processing.org/tutorials/pixels
總結(jié)
以上是生活随笔為你收集整理的图像和像素(Images and Pixels)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: php 拼接html字符串,php截断带
- 下一篇: pandas(四)pandas的拼接操作