This commit is contained in:
Gašper Dobrovoljc 2024-03-30 22:23:04 +01:00
parent 22043e58f5
commit a460c4de28
No known key found for this signature in database
GPG Key ID: 0E7E037018CFA5A5
4 changed files with 529 additions and 0 deletions

2
konvolucija1.p2 Normal file
View File

@ -0,0 +1,2 @@
P2: 4 x 4
0 64 128 255 255 128 64 0 0 0 1 1 255 255 37 5

2
slika.p2 Normal file
View File

@ -0,0 +1,2 @@
P2: 15 x 10
0 0 128 128 128 164 164 164 164 164 128 128 128 0 0 0 255 255 255 0 0 255 255 255 255 255 255 255 255 0 128 255 255 0 255 255 0 255 255 255 16 255 16 255 128 128 255 0 255 255 255 255 0 255 255 255 16 255 255 128 164 255 0 255 255 255 255 0 255 255 16 255 16 255 164 164 255 255 0 255 255 0 255 255 244 255 255 244 255 164 128 255 255 255 0 0 255 255 255 255 244 244 255 255 128 128 255 144 255 255 255 255 144 255 255 244 244 255 255 128 0 255 255 255 255 255 255 255 255 244 255 255 244 255 0 0 0 128 128 128 164 164 164 164 164 128 128 128 0 0

2
slikaB.p2 Normal file
View File

@ -0,0 +1,2 @@
P2B: 4 x 3
1072693248 1072693248 1073741823 672794241 1073741823 1047552 1047552 1073741823 0 1073741823 1023 1023

523
src/DN05.java Normal file
View File

@ -0,0 +1,523 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DN05 {
public static void main(String[] args) {
if (args[0].equals("barvna") || args[0].equals("sivinska")) {
int[][][] barvnaSlika = preberiBarvnoSliko(args[1]);
if (barvnaSlika == null) return;
switch (args[0]) {
case "barvna":
izpisiBarvnoSliko(barvnaSlika);
return;
case "sivinska":
izpisiSliko(pretvoriVSivinsko(barvnaSlika));
return;
}
}
int[][] slika = preberiSliko(args[1]);
if (slika == null) return;
switch (args[0]) {
case "izpisi":
izpisiSliko(slika);
break;
case "histogram":
izpisiHistogram(slika);
break;
case "svetlost":
System.out.printf("Srednja vrednost sivine na sliki %s je: %.2f\n", args[1], svetlostSlike(slika));
break;
case "zmanjsaj":
izpisiSliko(zmanjsajSliko(slika));
break;
case "rotiraj":
izpisiSliko(rotirajSliko(slika));
break;
case "zrcali":
izpisiSliko(zrcaliSliko(slika));
break;
case "vrstica":
System.out.printf("Max razlika svetlo - temno je v %d. vrstici.\n", poisciMaxVrstico(slika));
break;
case "uredi":
preberiVseInIzpisi(Arrays.stream(args).skip(1).toArray(String[]::new));
break;
case "jedro":
konvolucijaJedro(slika);
break;
case "glajenje":
konvolucijaGlajenje(slika);
break;
case "robovi":
konvolucijaRobovi(slika);
break;
default:
System.out.println("Napaka: Neveljaven argument.");
}
}
static int[][] preberiSliko(String ime) {
File file = new File(ime);
Scanner scanner;
try {
scanner = new Scanner(file);
} catch (FileNotFoundException e) {
System.out.printf("Napaka: datoteka %s ne obstaja.\n", ime);
return null;
}
if (!scanner.hasNextLine()) {
System.out.printf("Napaka: Datoteka %s je prazna.\n", ime);
return null;
}
String format = scanner.nextLine();
Pattern pattern = Pattern.compile("^P2: (.+) x (.+)$");
Matcher matcher = pattern.matcher(format);
if (!matcher.matches()) {
System.out.printf("Napaka: datoteka %s ni v formatu P2.\n", ime);
return null;
}
int width, height;
try {
width = Integer.parseInt(matcher.group(1));
height = Integer.parseInt(matcher.group(2));
} catch (NumberFormatException e) {
System.out.printf("Napaka: datoteka %s ni v formatu P2 (velikost slike ni pravilna).\n", ime);
return null;
}
if (width <= 0 || height <= 0) {
System.out.printf("Napaka: datoteka %s ni v formatu P2 (velikost slike je 0 ali negativna).\n", ime);
return null;
}
if (!scanner.hasNextLine()) {
System.out.printf("Napaka: datoteka %s vsebuje premalo podatkov.\n", ime);
return null;
}
String[] data = scanner.nextLine().split(" ");
if (data.length < width * height) {
System.out.printf("Napaka: datoteka %s vsebuje premalo podatkov.\n", ime);
return null;
}
int[][] image = new int[height][width];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int p = Integer.parseInt(data[i * width + j]);
if (p < 0 || p > 255) {
System.out.printf("Napaka: datoteka %s vsebuje podatke izven obsega 0 do 255.\n", ime);
return null;
}
image[i][j] = p;
}
}
return image;
}
static void izpisiSliko(int[][] slika) {
System.out.printf("velikost slike: %d x %d\n", slika[0].length, slika.length);
for (int[] row : slika) {
for (int p : row) {
System.out.printf("%3d ", p);
}
System.out.println();
}
}
static void izpisiHistogram(int[][] slika) {
int[] histogram = new int[256];
for (int[] row : slika) {
for (int p : row) {
histogram[p]++;
}
}
System.out.println("sivina : # pojavitev");
for (int i = 0; i < 256; i++) {
if (histogram[i] == 0) continue;
System.out.printf(" %3d : %d\n", i, histogram[i]);
}
}
static double svetlostSlike(int[][] slika) {
double sum = 0;
for (int[] row : slika) {
for (int p : row) {
sum += p;
}
}
return sum / (slika.length * slika[0].length);
}
static int[][] zmanjsajSliko(int[][] slika) {
int width = slika[0].length;
int height = slika.length;
if (width < 3 || height < 3) {
return slika;
}
int newWidth = width / 2;
int newHeight = height / 2;
int[][] newImage = new int[newHeight][newWidth];
for (int i = 0; i < newHeight; i++) {
for (int j = 0; j < newWidth; j++) {
newImage[i][j] = (slika[i * 2][j * 2] + slika[i * 2][j * 2 + 1] + slika[i * 2 + 1][j * 2] + slika[i * 2 + 1][j * 2 + 1]) / 4;
}
}
return newImage;
}
static int[][] rotirajSliko(int[][] slika) {
int width = slika[0].length;
int height = slika.length;
int[][] newImage = new int[width][height];
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
newImage[i][j] = slika[height - j - 1][i];
}
}
return newImage;
}
static int[][] zrcaliSliko(int[][] slika) {
int width = slika[0].length;
int height = slika.length;
int[][] newImage = new int[height][width];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
newImage[i][j] = slika[i][width - j - 1];
}
}
return newImage;
}
static int poisciMaxVrstico(int[][] slika) {
int maxDiff = 0;
int maxDiffIndex = 0;
for (int i = 0; i < slika.length; i++) {
int min = slika[i][0];
int max = slika[i][0];
for (int j = 1; j < slika[i].length; j++) {
if (slika[i][j] < min) {
min = slika[i][j];
}
if (slika[i][j] > max) {
max = slika[i][j];
}
}
int diff = max - min;
if (diff > maxDiff) {
maxDiff = diff;
maxDiffIndex = i;
}
}
return maxDiffIndex + 1;
}
static int[][][] preberiBarvnoSliko(String ime) {
File file = new File(ime);
Scanner scanner;
try {
scanner = new Scanner(file);
} catch (FileNotFoundException e) {
System.out.printf("Napaka: datoteka %s ne obstaja.\n", ime);
return null;
}
if (!scanner.hasNextLine()) {
System.out.printf("Napaka: Datoteka %s je prazna.\n", ime);
return null;
}
String format = scanner.nextLine();
Pattern pattern = Pattern.compile("^P2B: (.+) x (.+)$");
Matcher matcher = pattern.matcher(format);
if (!matcher.matches()) {
System.out.printf("Napaka: datoteka %s ni v formatu P2B.\n", ime);
return null;
}
int width, height;
try {
width = Integer.parseInt(matcher.group(1));
height = Integer.parseInt(matcher.group(2));
} catch (NumberFormatException e) {
System.out.printf("Napaka: datoteka %s ni v formatu P2B (velikost slike ni pravilna).\n", ime);
return null;
}
if (width <= 0 || height <= 0) {
System.out.printf("Napaka: datoteka %s ni v formatu P2B (velikost slike je 0 ali negativna).\n", ime);
return null;
}
if (!scanner.hasNextLine()) {
System.out.printf("Napaka: datoteka %s vsebuje premalo podatkov.\n", ime);
return null;
}
String[] data = scanner.nextLine().split(" ");
if (data.length < width * height) {
System.out.printf("Napaka: datoteka %s vsebuje premalo podatkov.\n", ime);
return null;
}
int[][][] image = new int[height][width][3];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int p = Integer.parseInt(data[i * width + j]);
int mask = 0b1111111111;
image[i][j][2] = p & mask;
image[i][j][1] = (p >> 10) & mask;
image[i][j][0] = (p >> 20) & mask;
}
}
return image;
}
static void izpisiBarvnoSliko(int[][][] slika) {
System.out.println("velikost slike: " + slika[0].length + " x " + slika.length);
for (int[][] row : slika) {
for (int[] p : row) {
System.out.printf("(%4d, %4d, %4d) ", p[0], p[1], p[2]);
}
System.out.println();
}
}
static int[][] pretvoriVSivinsko(int[][][] slika) {
int width = slika[0].length;
int height = slika.length;
int[][] newImage = new int[height][width];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
newImage[i][j] = (slika[i][j][0] + slika[i][j][1] + slika[i][j][2]) / 3 * 255 / 1023;
}
}
return newImage;
}
static void preberiVseInIzpisi(String[] imenaSlik) {
int[][] map = new int[imenaSlik.length][2];
for (int i = 0; i < imenaSlik.length; i++) {
int[][] slika = preberiSliko(imenaSlik[i]);
if (slika == null) continue;
int svetlost = (int) Math.round(svetlostSlike(slika));
map[i][0] = svetlost;
map[i][1] = i;
}
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map.length - i - 1; j++) {
if (map[j][0] < map[j + 1][0] || (map[j][0] == map[j + 1][0] && imenaSlik[map[j][1]].compareToIgnoreCase(imenaSlik[map[j + 1][1]]) > 0)) {
int[] temp = map[j];
map[j] = map[j + 1];
map[j + 1] = temp;
}
}
}
for (int[] pair : map) {
System.out.printf("%s (%d)\n", imenaSlik[pair[1]], pair[0]);
}
}
static void konvolucijaJedro(int[][] slika) {
int[][] jedro = {
{1, 1, 1},
{1, 1, 1},
{1, 1, 1}
};
int width = slika[0].length;
int height = slika.length;
int[][] novaSlika = new int[height - 2][width - 2];
for (int i = 1; i < height - 1; i++) {
for (int j = 1; j < width - 1; j++) {
int sum = 0;
for (int k = -1; k <= 1; k++) {
for (int l = -1; l <= 1; l++) {
sum += slika[i + k][j + l] * jedro[k + 1][l + 1];
}
}
novaSlika[i - 1][j - 1] = sum;
}
}
izpisiSliko(novaSlika);
}
static int[][] razsiriSliko(int[][] slika) {
int w = slika[0].length;
int h = slika.length;
int[][] razsirjena = new int[h + 2][w + 2];
for (int i = 0; i < razsirjena.length; i++) {
for (int j = 0; j < razsirjena[i].length; j++) {
if (i == 0 && j == 0) {
razsirjena[i][j] = slika[0][0];
} else if (i == 0 && j == w + 1) {
razsirjena[i][j] = slika[0][w - 1];
} else if (i == h + 1 && j == 0) {
razsirjena[i][j] = slika[h - 1][0];
} else if (i == h + 1 && j == w + 1) {
razsirjena[i][j] = slika[h - 1][w - 1];
} else if (i == 0) {
razsirjena[i][j] = slika[0][j - 1];
} else if (i == h + 1) {
razsirjena[i][j] = slika[h - 1][j - 1];
} else if (j == 0) {
razsirjena[i][j] = slika[i - 1][0];
} else if (j == w + 1) {
razsirjena[i][j] = slika[i - 1][w - 1];
} else {
razsirjena[i][j] = slika[i - 1][j - 1];
}
}
}
return razsirjena;
}
static void konvolucijaGlajenje(int[][] slika) {
double[][] jedro = {
{16, 8, 16},
{8, 4, 8},
{16, 8, 16},
};
int width = slika[0].length;
int height = slika.length;
int[][] razsirjenaSlika = razsiriSliko(slika);
int[][] novaSlika = new int[height][width];
for (int i = 1; i <= height; i++) {
for (int j = 1; j <= width; j++) {
int sum = 0;
for (int k = -1; k <= 1; k++) {
for (int l = -1; l <= 1; l++) {
sum += (int) Math.round(razsirjenaSlika[i + k][j + l] / jedro[k + 1][l + 1]);
}
}
novaSlika[i - 1][j - 1] = sum;
}
}
izpisiSliko(novaSlika);
}
static void konvolucijaRobovi(int[][] slika) {
int width = slika[0].length;
int height = slika.length;
int[][] razsirjenaSlika = razsiriSliko(slika);
int[][] navpicni = {
{1, 0, -1},
{2, 0, -2},
{1, 0, -1}
};
int[][] roboviNavpicno = new int[height][width];
for (int i = 1; i <= height; i++) {
for (int j = 1; j <= width; j++) {
int sum = 0;
for (int k = -1; k <= 1; k++) {
for (int l = -1; l <= 1; l++) {
sum += razsirjenaSlika[i + k][j + l] * navpicni[k + 1][l + 1];
}
}
roboviNavpicno[i - 1][j - 1] = sum;
}
}
int[][] vodoravni = {
{1, 2, 1},
{0, 0, 0},
{-1, -2, -1}
};
int[][] roboviVodoravno = new int[height][width];
for (int i = 1; i <= height; i++) {
for (int j = 1; j <= width; j++) {
int sum = 0;
for (int k = -1; k <= 1; k++) {
for (int l = -1; l <= 1; l++) {
sum += razsirjenaSlika[i + k][j + l] * vodoravni[k + 1][l + 1];
}
}
roboviVodoravno[i - 1][j - 1] = sum;
}
}
int[][] roboviSkupaj = new int[height][width];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
roboviSkupaj[i][j] = (int) Math.round(Math.sqrt(roboviNavpicno[i][j] * roboviNavpicno[i][j] + roboviVodoravno[i][j] * roboviVodoravno[i][j]));
}
}
int max = 0;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
max = Math.max(max, roboviSkupaj[i][j]);
}
}
int[][] roboviKoncni = new int[height][width];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
roboviKoncni[i][j] = (int) Math.round(roboviSkupaj[i][j] * 255.0 / max);
}
}
izpisiSliko(roboviKoncni);
}
}