diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/ImageSimilarityService.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/ImageSimilarityService.java new file mode 100644 index 000000000..e0e538994 --- /dev/null +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/ImageSimilarityService.java @@ -0,0 +1,96 @@ +package com.iqser.red.service.persistence.management.v1.processor.service; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.iqser.red.service.persistence.management.v1.processor.service.FileManagementStorageService; +import com.iqser.red.service.persistence.service.v1.api.shared.model.utils.Scope; +import com.iqser.red.service.persistence.service.v1.api.shared.mongo.document.ImageDocument; +import com.iqser.red.service.persistence.service.v1.api.shared.mongo.service.ImageMongoService; +import com.knecon.fforesight.service.layoutparser.internal.api.data.redaction.DocumentStructure; +import com.knecon.fforesight.service.layoutparser.internal.api.data.redaction.NodeType; +import com.knecon.fforesight.tenantcommons.TenantContext; + +import lombok.extern.slf4j.Slf4j; + +@Service +@Slf4j +public class ImageSimilarityService { + + @Autowired + ImageMongoService imageMongoService; + @Autowired + FileManagementStorageService fileManagementStorageService; + @Autowired + ObjectMapper objectMapper; + + + //load all recat requests and find similiar images + public void saveImages(String templateId, String dossierId, String fileId, String storageId) throws IOException { + //load structure files of all files in template + List imageDocuments = new ArrayList<>(); + try (InputStream inputStream = fileManagementStorageService.getObject(TenantContext.getTenantId(), storageId)) { + //load images from structures + DocumentStructure documentStructure = objectMapper.readValue(inputStream, DocumentStructure.class); + documentStructure.streamAllEntries() + .filter(entry -> entry.getType().equals(NodeType.IMAGE)) + .forEach(i -> { + Map properties = i.getProperties(); + ImageDocument imageDocument = new ImageDocument(); + imageDocument.setImageId(properties.get("id")); + imageDocument.setFeatureVector(parseRepresentationVector(properties.get("representationHash"))); + imageDocument.setTemplateId(templateId); + imageDocument.setDossierId(dossierId); + imageDocument.setFileId(fileId); + imageDocuments.add(imageDocument); + + }); + } + if (imageDocuments.isEmpty()) { + return; + } + imageMongoService.saveImages(imageDocuments); + } + + + public List findSimilarImages(String centroId, double distance, Scope scope) throws Exception { + + ImageDocument centroImage = this.imageMongoService.findById(centroId); + log.info("image received with id {}: {}",centroId, centroImage); + List similarImages = this.imageMongoService.findSimilarImages(centroImage, distance, scope); + log.info("received similar images: {}",similarImages); + return similarImages.stream() + .collect(Collectors.toList()); + } + + + public static double[] parseRepresentationVector(String representationHash) { + + double[] doubleArray = new double[representationHash.length()]; + + for (int i = 0; i < representationHash.length(); i++) { + char c = representationHash.charAt(i); + if (Character.isDigit(c)) { + // Convert numeric characters directly to their numeric values + doubleArray[i] = Character.getNumericValue(c); + } else if (Character.isLetter(c)) { + // Convert alphabetic characters to their position in the alphabet + // 'A' or 'a' -> 10, 'B' or 'b' -> 11, ..., 'F' or 'f' -> 15 + doubleArray[i] = 10 + Character.toUpperCase(c) - 'A'; + } else { + throw new IllegalArgumentException("Invalid character in input string: " + c); + } + } + + return doubleArray; + } + +} \ No newline at end of file diff --git a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/queue/LayoutParsingFinishedMessageReceiver.java b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/queue/LayoutParsingFinishedMessageReceiver.java index 2c1c8d146..7035abacc 100644 --- a/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/queue/LayoutParsingFinishedMessageReceiver.java +++ b/persistence-service-v1/persistence-service-processor-v1/src/main/java/com/iqser/red/service/persistence/management/v1/processor/service/queue/LayoutParsingFinishedMessageReceiver.java @@ -13,8 +13,8 @@ import com.iqser.red.service.persistence.management.v1.processor.migration.SaasM import com.iqser.red.service.persistence.management.v1.processor.model.websocket.AnalyseStatus; import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusProcessingUpdateService; import com.iqser.red.service.persistence.management.v1.processor.service.FileStatusService; +import com.iqser.red.service.persistence.management.v1.processor.service.ImageSimilarityService; import com.iqser.red.service.persistence.management.v1.processor.service.WebsocketService; -import com.iqser.red.service.persistence.management.v1.processor.service.image.ImageSimilarityService; import com.iqser.red.service.persistence.management.v1.processor.service.layoutparsing.LayoutParsingRequestIdentifierService; import com.iqser.red.service.persistence.management.v1.processor.service.persistence.SaasMigrationStatusPersistenceService; import com.iqser.red.service.persistence.management.v1.processor.utils.StorageIdUtils; @@ -39,7 +39,7 @@ public class LayoutParsingFinishedMessageReceiver { private final LayoutParsingRequestIdentifierService layoutParsingRequestIdentifierService; private final SaasMigrationStatusPersistenceService saasMigrationStatusPersistenceService; private final SaasMigrationService saasMigrationService; - private final ImageSimilarityService imageSimiliarityService; + private final ImageSimilarityService imageSimilarityService; private final WebsocketService websocketService; @@ -64,7 +64,7 @@ public class LayoutParsingFinishedMessageReceiver { fileStatusService.updateLayoutProcessedTime(layoutParsingRequestIdentifierService.parseFileId(response.identifier())); websocketService.sendAnalysisEvent(dossierId, fileId, AnalyseStatus.LAYOUT_UPDATE, fileStatusService.getStatus(fileId).getNumberOfAnalyses() + 1); - imageSimiliarityService.saveImages(templateId, dossierId, fileId, storageId); + imageSimilarityService.saveImages(templateId, dossierId, fileId, storageId); log.info("Received message {} in {}", response, LayoutParsingQueueNames.LAYOUT_PARSING_FINISHED_EVENT_QUEUE); }