提问人:upd 提问时间:11/13/2023 更新时间:11/13/2023 访问量:17
.jpe 和 .jxr 文件扩展名的 Java PhotoHashing 问题
Java PhotoHashing problem with .jpe and .jxr file extensions
问:
我写了一个代码来扫描目录并为照片提供 pHash。问题是,当我为 8 张具有不同扩展名的相同照片指定路径时,即(.bmp .jpe .jpeg .jpeg .jpg .jpg .jxr .png .tif .tiff),它只计算其中 6 张的 pHash(它不会为 .jpe 和 .jxr 执行此操作)。终端是这样说的:
File: pepedefault.bmp, pHash: 111111111111111000000111111111111111111000000000000111111111111100000000000000011111111111000000000000000011111111110100000000000000001111111000000000000000000001111100000000000000000000001111000000000000000000000001110000000000000000000000001100000000000000000001000001100000000000000000011100000100000000000000000011100000000000000010000000011100000100000000011000000011100000100000000111000000011100000100000000100000000011100000110000000111000000011100000110000001000000000011100000100000001010000000011100001100000001100000000011100001000000001110000000001100001000000001110000000001100001000000000110000000001100001100000001110000000001100011100000001110000000011100011110000001000000000011100111111100001110000000011100111111100010100000000011111111111110010100000000011111111111111011100111000111111111111111001101111110111111111111111111111111111111111111
net.coobird.thumbnailator.tasks.UnsupportedFormatException: No suitable ImageWriter found for jpe.
at net.coobird.thumbnailator.tasks.io.FileImageSink.isMatchingFormat(Unknown Source)
at net.coobird.thumbnailator.tasks.io.FileImageSink.write(Unknown Source)
at net.coobird.thumbnailator.tasks.SourceSinkThumbnailTask.write(Unknown Source)
at net.coobird.thumbnailator.Thumbnailator.createThumbnail(Unknown Source)
at net.coobird.thumbnailator.Thumbnails$Builder.toFile(Unknown Source)
at org.example.PhotoHashing.resizeImage(PhotoHashing.java:86)
at org.example.PhotoHashing.computePHash(PhotoHashing.java:59)
at org.example.PhotoHashing.main(PhotoHashing.java:24)
File: pepedefault.jpeg, pHash: 111111111111110000000011111111111111110000000000000111111111111100000000000000011111111111000000000000000011111111110000000000000000001111111000000000000000000001111100000000000000000000001111000000000000000000000001110000000000000000000000001100000000000000000000000000100000000000000000011100000100000000000000000011100000000000000011000000011100000000000000011000000011100000100000000111000000011100000100000000100000000011100000110000000111000000011100000110000001000000000011100000100000001010000000011100000100000001100000000011100001000000001110000000001100001000000000110000000001100001000000001110000000001110001100000001110000000001110011100000001110000000001100011110000001000000000001110111111100001110000000011110111111100010100000000010111111111110010100000000011111111111110011100111000011111111111111001101111110111111111111111111111111111111111111
File: pepedefault.tif, pHash: 111111111111111000000111111111111111111000000000000111111111111100000000000000011111111111000000000000000011111111110100000000000000001111111000000000000000000001111100000000000000000000001111000000000000000000000001110000000000000000000000001100000000000000000001000001100000000000000000011100000100000000000000000011100000000000000010000000011100000100000000011000000011100000100000000111000000011100000100000000100000000011100000110000000111000000011100000110000001000000000011100000100000001010000000011100001100000001100000000011100001000000001110000000001100001000000001110000000001100001000000000110000000001100001100000001110000000001100011100000001110000000011100011110000001000000000011100111111100001110000000011100111111100010100000000011111111111110010100000000011111111111111011100111000111111111111111001101111110111111111111111111111111111111111111
File: pepedefault.tiff, pHash: 111111111111111000000111111111111111111000000000000111111111111100000000000000011111111111000000000000000011111111110100000000000000001111111000000000000000000001111100000000000000000000001111000000000000000000000001110000000000000000000000001100000000000000000001000001100000000000000000011100000100000000000000000011100000000000000010000000011100000100000000011000000011100000100000000111000000011100000100000000100000000011100000110000000111000000011100000110000001000000000011100000100000001010000000011100001100000001100000000011100001000000001110000000001100001000000001110000000001100001000000000110000000001100001100000001110000000001100011100000001110000000011100011110000001000000000011100111111100001110000000011100111111100010100000000011111111111110010100000000011111111111111011100111000111111111111111001101111110111111111111111111111111111111111111
File: pepedefault.jpg, pHash: 111111111111110000000011111111111111110000000000000111111111111100000000000000011111111111000000000000000011111111110000000000000000001111111000000000000000000001111100000000000000000000001111000000000000000000000001110000000000000000000000001100000000000000000000000000100000000000000000011100000100000000000000000011100000000000000011000000011100000000000000011000000011100000100000000111000000011100000100000000100000000011100000110000000111000000011100000110000001000000000011100000100000001010000000011100000100000001100000000011100001000000001110000000001100001000000000110000000001100001000000001110000000001110001100000001110000000001110011100000001110000000001100011110000001000000000001110111111100001110000000011110111111100010100000000010101111111110010100000000011111111111110011100111000011111111111111001101111110111111111111111111111111111111111111
File: pepedefault.png, pHash: 111111111111111000000111111111111111111000000000000111111111111100000000000000011111111111000000000000000011111111110100000000000000001111111000000000000000000001111100000000000000000000001111000000000000000000000001110000000000000000000000001100000000000000000001000001100000000000000000011100000100000000000000000011100000000000000010000000011100000100000000011000000011100000100000000111000000011100000100000000100000000011100000110000000111000000011100000110000001000000000011100000100000001010000000011100001100000001100000000011100001000000001110000000001100001000000001110000000001100001000000000110000000001100001100000001110000000001100011100000001110000000011100011110000001000000000011100111111100001110000000011100111111100010100000000011111111111110010100000000011111111111111011100111000111111111111111001101111110111111111111111111111111111111111111
为了准确起见,我将提供我使用的文件,即: pom.xml PhotoHashing.java DCT.java
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>HashPicks</artifactId>
<version>1.0-SNAPSHOT</version>
<repositories>
<repository>
<id>downgoon</id>
<url>https://raw.githubusercontent.com/downgoon/maven-repo/master/repository</url>
</repository>
</repositories>
<dependencies>
<!-- Thumbnailator -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.14</version>
</dependency>
<dependency>
<groupId>javax.media</groupId>
<artifactId>jai_core</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>javax.media</groupId>
<artifactId>jai_core</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-jpeg</artifactId>
<version>3.10.1</version>
</dependency>
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-tiff</artifactId>
<version>3.10.1</version>
</dependency>
<!--
Optional dependency. Needed only if you deploy ImageIO plugins as part of a web app.
Make sure you add the IIOProviderContextListener to your web.xml, see above.
-->
<dependency>
<groupId>com.twelvemonkeys.servlet</groupId>
<artifactId>servlet</artifactId>
<version>3.10.1</version>
</dependency>
<!--
Or Jakarta version, for Servlet API 5.0
-->
<dependency>
<groupId>com.twelvemonkeys.servlet</groupId>
<artifactId>servlet</artifactId>
<version>3.10.1</version>
<classifier>jakarta</classifier>
</dependency>
<dependency>
<groupId>com.github.downgoon</groupId>
<artifactId>MarvinFramework</artifactId>
<version>1.5.5</version>
</dependency>
<!-- Thanks for using https://jar-download.com -->
<!-- Marvin Image Processing Framework -->
<dependency>
<groupId>com.github.downgoon</groupId>
<artifactId>marvin</artifactId>
<version>1.5.5</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
PhotoHashing.java
package org.example;
import net.coobird.thumbnailator.Thumbnails;
import marvin.image.MarvinImage;
import marvin.io.MarvinImageIO;
import marvin.plugin.MarvinImagePlugin;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class PhotoHashing {
public static void main(String[] args) {
// Путь к директории с фотографиями
String directoryPath = "/Users/dark_kat/Downloads/pepe";
// Получаем список файлов в директории
List<File> imageFiles = getSupportedImageFiles(directoryPath);
// Вычисляем и выводим pHash для каждой фотографии
for (File imageFile : imageFiles) {
try {
String pHash = computePHash(imageFile);
System.out.println("File: " + imageFile.getName() + ", pHash: " + pHash);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static List<File> getSupportedImageFiles(String directoryPath) {
// Получаем список поддерживаемых изображений из директории
List<File> imageFiles = new ArrayList<>();
File directory = new File(directoryPath);
if (directory.isDirectory()) {
for (File file : directory.listFiles()) {
if (file.isFile() && isSupportedImage(file)) {
imageFiles.add(file);
}
}
}
return imageFiles;
}
private static boolean isSupportedImage(File file) {
// Проверяем, является ли файл поддерживаемым изображением
String fileName = file.getName().toLowerCase();
return fileName.endsWith(".jpg") || fileName.endsWith(".jpeg") || fileName.endsWith(".jpe") ||
fileName.endsWith(".png") || fileName.endsWith(".tif") || fileName.endsWith(".tiff") ||
fileName.endsWith(".svg") || fileName.endsWith(".bmp") || fileName.endsWith(".webp") ||
fileName.endsWith(".jfif");
}
private static String computePHash(File imageFile) throws IOException {
// Изменяем размер изображения
File resizedImage = resizeImage(imageFile);
// Загружаем изображение
MarvinImage image = MarvinImageIO.loadImage(resizedImage.getPath());
// Выполняем дискретное косинусное преобразование (DCT)
MarvinImagePlugin dct = new DCT();
dct.process(image, image);
// Вычисляем среднее значение DCT
double averageDCT = computeAverageDCT(image);
// Ещё сокращаем DCT
reduceDCT(image, averageDCT);
// Построим хэш
String pHash = buildHash(image);
// Удаляем временные файлы
resizedImage.delete();
return pHash;
}
private static File resizeImage(File originalImage) throws IOException {
// Изменяем размер изображения до 32x32 пикселей
File resizedImage = new File("resized_" + originalImage.getName());
Thumbnails.of(originalImage).size(32, 32).toFile(resizedImage);
return resizedImage;
}
private static double computeAverageDCT(MarvinImage image) {
// Вычисляем среднее значение DCT
double sum = 0;
for (int x = 0; x < image.getWidth(); x++) {
for (int y = 0; y < image.getHeight(); y++) {
sum += image.getIntComponent0(x, y);
}
}
return sum / (image.getWidth() * image.getHeight());
}
private static void reduceDCT(MarvinImage image, double averageDCT) {
// Сокращаем DCT
for (int x = 0; x < image.getWidth(); x++) {
for (int y = 0; y < image.getHeight(); y++) {
if (image.getIntComponent0(x, y) > averageDCT) {
image.setIntColor(x, y, 255, 255, 255);
} else {
image.setIntColor(x, y, 0, 0, 0);
}
}
}
}
private static String buildHash(MarvinImage image) {
// Построим хэш, представляющий изображение
StringBuilder hash = new StringBuilder();
for (int x = 0; x < image.getWidth(); x++) {
for (int y = 0; y < image.getHeight(); y++) {
hash.append(image.getIntComponent0(x, y) > 0 ? "1" : "0");
}
}
return hash.toString();
}
}
DCT.java
// Путь к файлу: src/main/java/com/example/imageprocessing/DCT.java
package org.example;
import marvin.gui.MarvinAttributesPanel;
import marvin.gui.MarvinImagePanel;
import marvin.image.MarvinImage;
import marvin.image.MarvinImageMask;
import marvin.plugin.MarvinImagePlugin;
import marvin.util.MarvinAttributes;
import java.util.List;
public class DCT implements MarvinImagePlugin {
public void process(MarvinImage imageIn, MarvinImage imageOut, int x, int y, int width, int height) {
int[][] pixels = new int[width][height];
// Заполняем массив значениями пикселей изображения
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
pixels[i][j] = imageIn.getIntComponent0(x + i, y + j);
}
}
// Выполняем дискретное косинусное преобразование
double[][] dctResult = applyDCT(pixels);
// Записываем результат обратно в изображение
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
imageOut.setIntColor(x + i, y + j, (int) dctResult[i][j], (int) dctResult[i][j], (int) dctResult[i][j]);
}
}
}
private double[][] applyDCT(int[][] pixels) {
int width = pixels.length;
int height = pixels[0].length;
double[][] result = new double[width][height];
for (int u = 0; u < width; u++) {
for (int v = 0; v < height; v++) {
double sum = 0.0;
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
sum += Math.cos((2.0 * i + 1.0) / (2.0 * width) * u * Math.PI) *
Math.cos((2.0 * j + 1.0) / (2.0 * height) * v * Math.PI) *
(pixels[i][j] - 128); // Предварительно вычитаем 128 для центрирования
}
}
double cu = (u == 0) ? 1.0 / Math.sqrt(2) : 1.0;
double cv = (v == 0) ? 1.0 / Math.sqrt(2) : 1.0;
result[u][v] = 0.25 * cu * cv * sum;
}
}
return result;
}
@Override
public MarvinAttributesPanel getAttributesPanel() {
return null;
}
@Override
public void process(MarvinImage marvinImage, MarvinImage marvinImage1, MarvinAttributes marvinAttributes, MarvinImageMask marvinImageMask, boolean b) {
}
@Override
public void process(MarvinImage marvinImage, MarvinImage marvinImage1, MarvinImageMask marvinImageMask) {
}
@Override
public void process(MarvinImage marvinImage, MarvinImage marvinImage1, MarvinAttributes marvinAttributes) {
}
@Override
public void process(MarvinImage marvinImage, MarvinImage marvinImage1) {
}
@Override
public void process(List<MarvinImage> list, MarvinImage marvinImage) {
}
@Override
public void setImagePanel(MarvinImagePanel marvinImagePanel) {
}
@Override
public MarvinImagePanel getImagePanel() {
return null;
}
@Override
public void load() {
}
@Override
public void validate() {
}
@Override
public void invalidate() {
}
@Override
public boolean isValid() {
return false;
}
@Override
public MarvinAttributes getAttributes() {
return null;
}
@Override
public void setAttribute(String s, Object o) {
}
@Override
public void setAttributes(Object... objects) {
}
@Override
public Object getAttribute(String s) {
return null;
}
}
尝试使用 TwelveMonkeys 库,但它没有影响任何事情,只是让它变得更糟。希望能帮到你!
答: 暂无答案
评论