我想將基于影像的直方圖轉換為矢量圖形。
這可能是一個開始:
function preload() {
img = loadImage("https://upload.wikimedia.org/wikipedia/commons/thumb/3/36/Cirrus_sky_panorama.jpg/1200px-Cirrus_sky_panorama.jpg");
}
function setup() {
createCanvas(400, 400);
background(255);
img.resize(0, 200);
var maxRange = 256
colorMode(HSL, maxRange);
image(img, 0, 0);
var histogram = new Array(maxRange);
for (i = 0; i <= maxRange; i ) {
histogram[i] = 0
}
loadPixels();
for (var x = 0; x < img.width; x = 5) {
for (var y = 0; y < img.height; y = 5) {
var loc = (x y * img.width) * 4;
var h = pixels[loc];
var s = pixels[loc 1];
var l = pixels[loc 2];
var a = pixels[loc 3];
b = int(l);
histogram[b]
}
}
image(img, 0, 0);
stroke(300, 100, 80)
push()
translate(10, 0)
for (x = 0; x <= maxRange; x ) {
index = histogram[x];
y1 = int(map(index, 0, max(histogram), height, height - 300));
y2 = height
xPos = map(x, 0, maxRange, 0, width - 20)
line(xPos, y1, xPos, y2);
}
pop()
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/p5.js"></script>
但我需要可下載的矢量圖形檔案作為結果,這些檔案是封閉的形狀,之間沒有任何間隙。例如,它應該看起來像這樣:
<svg viewBox="0 0 399.84 200"><polygon points="399.84 200 399.84 192.01 361.91 192.01 361.91 182.87 356.24 182.87 356.24 183.81 350.58 183.81 350.58 184.74 344.91 184.74 344.91 188.19 339.87 188.19 339.87 189.89 334.6 189.89 334.6 185.29 328.93 185.29 328.93 171.11 323.26 171.11 323.26 172.55 317.59 172.55 317.59 173.99 311.92 173.99 311.92 179.42 306.88 179.42 306.88 182.03 301.21 182.03 301.21 183.01 295.54 183.01 295.54 179.04 289.87 179.04 289.87 175.67 284.21 175.67 284.21 182.03 278.54 182.03 278.54 176 273.5 176 273.5 172.42 267.83 172.42 267.83 179.42 262.79 179.42 262.79 182.03 257.12 182.03 257.12 183.01 251.45 183.01 251.45 178.63 245.78 178.63 245.78 175.21 240.11 175.21 240.11 182.03 234.86 182.03 234.86 150.42 229.2 150.42 229.2 155.98 223.53 155.98 223.53 158.06 217.86 158.06 217.86 167.44 212.19 167.44 212.19 162.58 206.52 162.58 206.52 155.98 200.85 155.98 200.85 158.06 195.18 158.06 195.18 167.44 189.51 167.44 189.51 177.46 183.84 177.46 183.84 166.93 178.17 166.93 178.17 153.69 172.5 153.69 172.5 155.87 166.82 155.87 166.82 158.05 161.78 158.05 161.78 155.63 156.11 155.63 156.11 160.65 150.84 160.65 150.84 146.59 145.17 146.59 145.17 109.63 139.49 109.63 139.49 113.67 133.82 113.67 133.82 61.48 128.15 61.48 128.15 80.59 123.11 80.59 123.11 93.23 117.44 93.23 117.44 97.97 111.76 97.97 111.76 78.07 106.09 78.07 106.09 61.66 100.42 61.66 100.42 93.23 94.75 93.23 94.75 98.51 89.7 98.51 89.7 85.4 84.03 85.4 84.03 111.03 78.99 111.03 78.99 120.57 73.32 120.57 73.32 124.14 67.65 124.14 67.65 23.48 61.97 23.48 61.97 0 56.3 0 56.3 120.57 50.63 120.57 50.63 167.01 45.38 167.01 45.38 170.83 39.71 170.83 39.71 172.26 34.03 172.26 34.03 178.7 28.36 178.7 28.36 175.36 22.69 175.36 22.69 170.83 17.02 170.83 17.02 172.26 11.34 172.26 11.34 178.7 5.67 178.7 5.67 103.85 0 103.85 0 200 399.84 200"/></svg>
有誰知道如何編程?它不一定需要基于 p5.js,但會很酷。
uj5u.com熱心網友回復:
縮小差距
為了獲得無間隙直方圖,您需要滿足以下條件:
numberOfBars * barWidth === totalWidth
現在您正在使用 p5line()函式來繪制條形圖。您沒有明確設定條形的寬度,因此它使用默認值1px寬度。
我們知道numberOfBars您的代碼中的始終maxRange是256.
現在直方圖的總寬度是width - 20,其中width設定400為createCanvas(400, 400)。所以totalWidth是380。
256 * 1 !== 380
如果在 380 像素的空間中有 256 像素的條,那么就會有間隙!
我們需要改變barWidth和/或totalWidth來平衡方程。
例如,您可以將畫布大小更改為276( 256 your 20px margin) 并且間隙消失!
createCanvas(276, 400);
然而,這不是一個合適的解決方案,因為現在您的影像被裁剪并且您的像素資料是錯誤的。但其實……之前就已經錯了!
采樣像素
當您loadPixels()在 p5.js 中呼叫全域函式時,您正在加載整個畫布的所有像素。這包括影像之外的白色區域。
for (var x = 0; x < img.width; x = 5) {
for (var y = 0; y < img.height; y = 5) {
var loc = (x y * img.width) * 4;
它是一個一維陣列,因此您在此處限制xandy值的方法并沒有為您提供正確的位置。您的loc變數需要使用整個畫布的寬度,而不僅僅是影像的寬度,因為像素陣列包括整個畫布。
var loc = (x y * width) * 4;
或者,您可以使用和僅查看影像的像素。img.loadPixels()img.pixels
img.loadPixels();
for (var x = 0; x < img.width; x = 5) {
for (var y = 0; y < img.height; y = 5) {
var loc = (x y * img.width) * 4;
var h = img.pixels[loc];
var s = img.pixels[loc 1];
var l = img.pixels[loc 2];
var a = img.pixels[loc 3];
b = int(l);
histogram[b] ;
}
}
無論colorMode. 所以你的第三個通道值實際上是blue,而不是lightness。您可以使用
function preload() {
img = loadImage("https://upload.wikimedia.org/wikipedia/commons/thumb/3/36/Cirrus_sky_panorama.jpg/1200px-Cirrus_sky_panorama.jpg");
}
function setup() {
const barCount = 100;
const imageHeight = 200;
createCanvas(400, 400);
background(255);
img.resize(0, imageHeight);
imageMode(CENTER);
image(img, width / 2, imageHeight / 2);
img.loadPixels();
const histogram = new Array(barCount).fill(0);
for (let x = 0; x < img.width; x = 5) {
for (let y = 0; y < img.height; y = 5) {
const loc = (x y * img.width) * 4;
const r = img.pixels[loc];
const g = img.pixels[loc 1];
const b = img.pixels[loc 2];
const a = img.pixels[loc 3];
const barIndex = floor(barCount * b / 255);
histogram[barIndex] ;
}
}
fill(100, 100, 300);
strokeWeight(0);
const maxCount = max(histogram);
const barWidth = width / barCount;
const histogramHeight = height - imageHeight;
for (let i = 0; i < barCount; i ) {
const count = histogram[i];
const y1 = round(map(count, 0, maxCount, height, imageHeight));
const y2 = height;
const x1 = i * barWidth;
const x2 = x1 barWidth;
rect(x1, y1, barWidth, height - y1);
}
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/p5.js"></script>
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/472822.html
