/
Sturon
/
Diplom
Обзор
Документация
Войти
/
Sturon
/
Diplom
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
backend/src/main/java/ru/diplom/vision/service/LocalInspectionService.java
142 строки
6 KB
Sturon
Initial
03 июн 2026, 15:01
03 июн 2026, 15:01
17b44a2
Код
Авторство
О чём код?
package ru.diplom.vision.service; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.util.List; import javax.imageio.ImageIO; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.server.ResponseStatusException; import ru.diplom.vision.api.dto.LocalInspectionRequest; import ru.diplom.vision.api.dto.LocalInspectionResponse; import ru.diplom.vision.api.dto.RoiZoneRequest; import ru.diplom.vision.domain.InspectionProfile; import ru.diplom.vision.domain.ProfileStatus; import ru.diplom.vision.domain.RegionOfInterest; import ru.diplom.vision.service.MockDetectorService.DefectCandidate; import static org.springframework.http.HttpStatus.BAD_REQUEST; import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR; @Service public class LocalInspectionService { private static final double DEFAULT_MIN_CONFIDENCE = 0.0; private static final int DEFAULT_MAX_DEFECTS = 0; private final InspectionProfileService inspectionProfileService; private final ReferenceImageService referenceImageService; private final MockCameraCaptureService mockCameraCaptureService; private final MockDetectorService mockDetectorService; public LocalInspectionService( InspectionProfileService inspectionProfileService, ReferenceImageService referenceImageService, MockCameraCaptureService mockCameraCaptureService, MockDetectorService mockDetectorService ) { this.inspectionProfileService = inspectionProfileService; this.referenceImageService = referenceImageService; this.mockCameraCaptureService = mockCameraCaptureService; this.mockDetectorService = mockDetectorService; } public LocalInspectionResponse evaluate(LocalInspectionRequest request, MultipartFile imageFile) { InspectionProfile profile = inspectionProfileService.getRequired(request.profileId()); validateProfile(profile); long startedAt = System.currentTimeMillis(); BufferedImage image = readImage(profile, imageFile); List<RegionOfInterest> rois = resolveRois(request.rois(), profile, image); double minConfidence = request.minConfidence() == null ? DEFAULT_MIN_CONFIDENCE : request.minConfidence(); int maxDefects = request.maxDefects() == null ? DEFAULT_MAX_DEFECTS : request.maxDefects(); List<DefectCandidate> defects = mockDetectorService.detect(image, rois).defects().stream() .filter(defect -> defect.confidence() >= minConfidence) .toList(); boolean result = defects.size() <= maxDefects; return new LocalInspectionResponse( result, defects.size(), System.currentTimeMillis() - startedAt, buildSummary(result, defects.size(), minConfidence, maxDefects) ); } private void validateProfile(InspectionProfile profile) { if (profile.getStatus() != ProfileStatus.ACTIVE) { throw new ResponseStatusException(BAD_REQUEST, "Точка контроля неактивна"); } if (!profile.getCameraSource().isActive()) { throw new ResponseStatusException(BAD_REQUEST, "Выбранная камера неактивна"); } } private BufferedImage readImage(InspectionProfile profile, MultipartFile imageFile) { if (imageFile == null) { return mockCameraCaptureService.captureImage(profile); } if (imageFile.isEmpty()) { throw new ResponseStatusException(BAD_REQUEST, "Файл изображения пустой"); } try (InputStream inputStream = imageFile.getInputStream()) { BufferedImage image = ImageIO.read(inputStream); if (image == null) { throw new ResponseStatusException(BAD_REQUEST, "Файл не является поддерживаемым изображением"); } return image; } catch (IOException exception) { throw new ResponseStatusException(INTERNAL_SERVER_ERROR, "Не удалось прочитать изображение"); } } private List<RegionOfInterest> resolveRois( List<RoiZoneRequest> requestRois, InspectionProfile profile, BufferedImage image ) { if (requestRois != null && !requestRois.isEmpty()) { return requestRois.stream() .map(request -> toRoi(request, image)) .toList(); } List<RegionOfInterest> profileRois = referenceImageService.getEffectiveRegionsOfInterest(profile.getReferenceImage()); if (!profileRois.isEmpty()) { return profileRois; } RegionOfInterest fullImage = new RegionOfInterest(); fullImage.setName("Полный кадр"); fullImage.setZoneOrder(0); fullImage.setX(0); fullImage.setY(0); fullImage.setWidth(image.getWidth()); fullImage.setHeight(image.getHeight()); return List.of(fullImage); } private RegionOfInterest toRoi(RoiZoneRequest request, BufferedImage image) { if (request.x() + request.width() > image.getWidth() || request.y() + request.height() > image.getHeight()) { throw new ResponseStatusException(BAD_REQUEST, "ROI выходит за границы изображения"); } RegionOfInterest roi = new RegionOfInterest(); roi.setName(request.name().trim()); roi.setZoneOrder(request.order()); roi.setX(request.x()); roi.setY(request.y()); roi.setWidth(request.width()); roi.setHeight(request.height()); return roi; } private String buildSummary(boolean result, int defectCount, double minConfidence, int maxDefects) { String verdict = result ? "Контроль пройден" : "Контроль не пройден"; return "%s: значимых дефектов %d, допустимо %d, порог уверенности %.2f" .formatted(verdict, defectCount, maxDefects, minConfidence); } }