| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- <?php
- namespace App\Services\OCR;
- use Intervention\Image\ImageManager;
- use Intervention\Image\Drivers\Gd\Driver;
- class ImageCropper
- {
- protected ImageManager $manager;
- public function __construct()
- {
- $this->manager = new ImageManager(new Driver());
- }
- /**
- * Crop answer area from exam paper image
- *
- * @param string $imagePath Full path to the image
- * @param array $coordinates ['x' => int, 'y' => int, 'width' => int, 'height' => int]
- * @return string Path to the cropped image
- */
- public function cropAnswerArea(string $imagePath, array $coordinates): string
- {
- $image = $this->manager->read($imagePath);
-
- // Get original dimensions
- $originalWidth = $image->width();
- $originalHeight = $image->height();
-
- // Default answer area: top-left corner (10% width, 15% height)
- $x = $coordinates['x'] ?? 0;
- $y = $coordinates['y'] ?? 0;
- $width = $coordinates['width'] ?? (int)($originalWidth * 0.1);
- $height = $coordinates['height'] ?? (int)($originalHeight * 0.15);
-
- // Crop the image
- $cropped = $image->crop($width, $height, $x, $y);
-
- // Save to temp directory
- $tempPath = storage_path('app/temp/answer_crops');
- if (!file_exists($tempPath)) {
- mkdir($tempPath, 0755, true);
- }
-
- $filename = 'answer_' . basename($imagePath);
- $outputPath = $tempPath . '/' . $filename;
-
- $cropped->save($outputPath);
-
- \Log::info('Cropped answer area', [
- 'original' => $imagePath,
- 'cropped' => $outputPath,
- 'dimensions' => "{$width}x{$height} at ({$x},{$y})"
- ]);
-
- return $outputPath;
- }
- /**
- * Crop answer area from a specific question's top-left corner
- *
- * @param string $imagePath Full path to the image
- * @param array $questionBbox Question's bounding box from Aliyun API
- * @return string Path to the cropped answer area
- */
- public function cropQuestionAnswerArea(string $imagePath, array $questionBbox): string
- {
- $image = $this->manager->read($imagePath);
-
- // Question bbox is typically: [{'x': int, 'y': int}, ...]
- // We need the top-left corner of the question area
- $minX = PHP_INT_MAX;
- $minY = PHP_INT_MAX;
- $maxX = 0;
- $maxY = 0;
-
- foreach ($questionBbox as $point) {
- $minX = min($minX, $point['x']);
- $minY = min($minY, $point['y']);
- $maxX = max($maxX, $point['x']);
- $maxY = max($maxY, $point['y']);
- }
-
- // Answer area: top-left corner of the question
- // Typically 10-15% of question width and height
- $questionWidth = $maxX - $minX;
- $questionHeight = $maxY - $minY;
-
- $answerWidth = (int)($questionWidth * 0.15);
- $answerHeight = (int)($questionHeight * 0.20);
-
- // Crop from top-left of question
- $cropped = $image->crop($answerWidth, $answerHeight, $minX, $minY);
-
- // Save to temp directory
- $tempPath = storage_path('app/temp/answer_crops');
- if (!file_exists($tempPath)) {
- mkdir($tempPath, 0755, true);
- }
-
- $filename = 'q_answer_' . uniqid() . '.jpg';
- $outputPath = $tempPath . '/' . $filename;
-
- $cropped->save($outputPath);
-
- return $outputPath;
- }
- }
|