Untitled

mail@pastecode.io avatar
unknown
plain_text
5 months ago
21 kB
3
Indexable
import 'dart:typed_data';
import 'dart:io' as io;
import 'dart:math';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:image/image.dart' as img;
import 'package:file_picker/file_picker.dart';

// dart:html sadece web için import edilir
import 'dart:html' as html
    if (dart.library.io) 'unsupported_platform.dart'; 

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ImageSquareDrawer(),
    );
  }
}

class ImageSquareDrawer extends StatefulWidget {
  @override
  _ImageSquareDrawerState createState() => _ImageSquareDrawerState();
}

class _ImageSquareDrawerState extends State<ImageSquareDrawer> {
  Uint8List? _selectedImageData;
  Uint8List? _edgeDetectedImageData;
  Rect? _highlightedRect;
  TextEditingController _coordinatesController = TextEditingController();

  Color? _color1;
  String _color1Hex = "";
  String _color1RGB = "";

  Future<void> _pickImageWeb() async {
    if (kIsWeb) {
      // Web için
      final uploadInput = html.FileUploadInputElement();
      uploadInput.accept = 'image/*';
      uploadInput.click();

      uploadInput.onChange.listen((e) {
        final files = uploadInput.files;
        if (files!.isEmpty) return;

        final reader = html.FileReader();
        reader.readAsArrayBuffer(files[0]);
        reader.onLoadEnd.listen((e) {
          setState(() {
            _selectedImageData = reader.result as Uint8List?;
            _highlightedRect = null;
            _edgeDetectedImageData = null;
          });
        });
      });
    } else {
      // Mobil platformlar için
      FilePickerResult? result = await FilePicker.platform.pickFiles(
        type: FileType.image,
      );

      if (result != null) {
        setState(() {
          _selectedImageData = result.files.first.bytes;
          _highlightedRect = null;
          _edgeDetectedImageData = null;
        });
      }
    }
  }

  void _setCoordinates(String coordinates) {
    _coordinatesController.text = coordinates;
    _drawSquare(coordinates);
  }

  void _drawSquare(String coordinates) {
    if (_selectedImageData == null) return;

    List<String> parts = coordinates.split(' ');
    double centerX = double.parse(parts[1]);
    double centerY = double.parse(parts[2]);
    double width = double.parse(parts[3]);
    double height = double.parse(parts[4]);

    double startX = centerX - width / 2;
    double startY = centerY - height / 2;

    setState(() {
      _highlightedRect = Rect.fromLTWH(startX, startY, width, height);
      _edgeDetectedImageData = null;
    });
  }

  img.Image _applyThreshold(img.Image image, int threshold) {
    img.Image grayImage = img.grayscale(image);
    img.Image thresholdedImage = img.Image.from(grayImage);

    for (int y = 0; y < thresholdedImage.height; y++) {
      for (int x = 0; x < thresholdedImage.width; x++) {
        int pixel = thresholdedImage.getPixel(x, y);
        int brightness = img.getLuminance(pixel);
        if (brightness < threshold) {
          thresholdedImage.setPixel(x, y, img.getColor(0, 0, 0));
        } else {
          thresholdedImage.setPixel(x, y, img.getColor(255, 255, 255));
        }
      }
    }

    return thresholdedImage;
  }

  void _applyEdgeDetection() {
    if (_selectedImageData == null) return;

    img.Image image = img.decodeImage(_selectedImageData!)!;

    List<String> coordinateSets = _coordinatesController.text.trim().split('\n');

    for (String coordinateSet in coordinateSets) {
      List<String> parts = coordinateSet.split(' ');
      int pieceNumber = int.parse(parts[0]);
      double centerX = double.parse(parts[1]);
      double centerY = double.parse(parts[2]);
      double width = double.parse(parts[3]);
      double height = double.parse(parts[4]);

      double startX = centerX - width / 2;
      double startY = centerY - height / 2;

      int rectX = (startX * image.width).toInt();
      int rectY = (startY * image.height).toInt();
      int rectWidth = (width * image.width).toInt();
      int rectHeight = (height * image.height).toInt();

      rectX = (rectX + rectWidth * 0.05).toInt();
      rectY = (rectY + rectHeight * 0.05).toInt();
      rectWidth = (rectWidth * 0.9).toInt();
      rectHeight = (rectHeight * 0.9).toInt();

      img.Image croppedImage = img.copyCrop(image, rectX, rectY, rectWidth, rectHeight);

      img.Image thresholdedImage = _applyThreshold(croppedImage, 128);
      img.Image edgeDetectedImage = img.sobel(thresholdedImage);

      List<Offset> contour = _findLargestContour(edgeDetectedImage);

      if (contour.isNotEmpty) {
        _drawContour(image, contour, rectX, rectY);
        Color averageColor = _calculateAverageColorInsideContour(image, contour, rectX, rectY);
        _drawColorOnPiece(image, pieceNumber, averageColor, rectX, rectY, rectWidth, rectHeight);
      }
    }

    _edgeDetectedImageData = Uint8List.fromList(img.encodePng(image));

    setState(() {});
  }

  List<Offset> _findLargestContour(img.Image edgeDetectedImage) {
    int maxArea = 0;
    List<Offset>? largestContour;

    for (int y = 0; y < edgeDetectedImage.height; y++) {
      for (int x = 0; x < edgeDetectedImage.width; x++) {
        int pixel = edgeDetectedImage.getPixel(x, y);
        if (img.getLuminance(pixel) > 0) {
          List<Offset> contour = _traceContour(edgeDetectedImage, x, y);
          if (contour.isNotEmpty) {
            int area = contour.length;
            if (area > 100) {
              if (area > maxArea) {
                maxArea = area;
                largestContour = contour;
              }
            }
          }
        }
      }
    }

    return largestContour ?? [];
  }

  List<Offset> _traceContour(img.Image image, int startX, int startY) {
    int x = startX;
    int y = startY;
    int dir = 0;
    List<Offset> contour = [];

    do {
      if (x >= 0 && x < image.width && y >= 0 && y < image.height) {
        contour.add(Offset(x.toDouble(), y.toDouble()));

        if (img.getLuminance(image.getPixel(x, y)) > 0) {
          image.setPixel(x, y, img.getColor(255, 0, 0, 255));
          dir = (dir + 3) % 4;
        } else {
          dir = (dir + 1) % 4;
        }
      } else {
        break;
      }

      switch (dir) {
        case 0: x += 1; break;
        case 1: y += 1; break;
        case 2: x -= 1; break;
        case 3: y -= 1; break;
      }

    } while ((x != startX || y != startY) && contour.length < 10000);

    return contour;
  }

  void _drawContour(img.Image image, List<Offset> contour, int offsetX, int offsetY) {
    int transparentColor = img.getColor(0, 0, 0, 0);

    for (int i = 0; i < contour.length - 1; i++) {
      _drawLine(
        image,
        Offset(contour[i].dx + offsetX, contour[i].dy + offsetY),
        Offset(contour[i + 1].dx + offsetX, contour[i + 1].dy + offsetY),
        transparentColor,
      );
    }

    _drawLine(
      image,
      Offset(contour.last.dx + offsetX, contour.last.dy + offsetY),
      Offset(contour.first.dx + offsetX, contour.first.dy + offsetY),
      transparentColor,
    );
  }

  void _drawLine(img.Image image, Offset p1, Offset p2, int color) {
    int x0 = p1.dx.toInt();
    int y0 = p1.dy.toInt();
    int x1 = p2.dx.toInt();
    int y1 = p2.dy.toInt();

    int dx = (x1 - x0).abs();
    int dy = (y1 - y0).abs();
    int sx = x0 < x1 ? 1 : -1;
    int sy = y0 < y1 ? 1 : -1;
    int err = dx - dy;

import 'dart:typed_data';
import 'dart:io' as io;
import 'dart:math';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:image/image.dart' as img;
import 'package:file_picker/file_picker.dart';

// dart:html sadece web için import edilir
import 'dart:html' as html
    if (dart.library.io) 'unsupported_platform.dart'; 

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ImageSquareDrawer(),
    );
  }
}

class ImageSquareDrawer extends StatefulWidget {
  @override
  _ImageSquareDrawerState createState() => _ImageSquareDrawerState();
}

class _ImageSquareDrawerState extends State<ImageSquareDrawer> {
  Uint8List? _selectedImageData;
  Uint8List? _edgeDetectedImageData;
  Rect? _highlightedRect;
  TextEditingController _coordinatesController = TextEditingController();

  Color? _color1;
  String _color1Hex = "";
  String _color1RGB = "";

  Future<void> _pickImageWeb() async {
    if (kIsWeb) {
      // Web için
      final uploadInput = html.FileUploadInputElement();
      uploadInput.accept = 'image/*';
      uploadInput.click();

      uploadInput.onChange.listen((e) {
        final files = uploadInput.files;
        if (files!.isEmpty) return;

        final reader = html.FileReader();
        reader.readAsArrayBuffer(files[0]);
        reader.onLoadEnd.listen((e) {
          setState(() {
            _selectedImageData = reader.result as Uint8List?;
            _highlightedRect = null;
            _edgeDetectedImageData = null;
          });
        });
      });
    } else {
      // Mobil platformlar için
      FilePickerResult? result = await FilePicker.platform.pickFiles(
        type: FileType.image,
      );

      if (result != null) {
        setState(() {
          _selectedImageData = result.files.first.bytes;
          _highlightedRect = null;
          _edgeDetectedImageData = null;
        });
      }
    }
  }

  void _setCoordinates(String coordinates) {
    _coordinatesController.text = coordinates;
    _drawSquare(coordinates);
  }

  void _drawSquare(String coordinates) {
    if (_selectedImageData == null) return;

    List<String> parts = coordinates.split(' ');
    double centerX = double.parse(parts[1]);
    double centerY = double.parse(parts[2]);
    double width = double.parse(parts[3]);
    double height = double.parse(parts[4]);

    double startX = centerX - width / 2;
    double startY = centerY - height / 2;

    setState(() {
      _highlightedRect = Rect.fromLTWH(startX, startY, width, height);
      _edgeDetectedImageData = null;
    });
  }

  img.Image _applyThreshold(img.Image image, int threshold) {
    img.Image grayImage = img.grayscale(image);
    img.Image thresholdedImage = img.Image.from(grayImage);

    for (int y = 0; y < thresholdedImage.height; y++) {
      for (int x = 0; x < thresholdedImage.width; x++) {
        int pixel = thresholdedImage.getPixel(x, y);
        int brightness = img.getLuminance(pixel);
        if (brightness < threshold) {
          thresholdedImage.setPixel(x, y, img.getColor(0, 0, 0));
        } else {
          thresholdedImage.setPixel(x, y, img.getColor(255, 255, 255));
        }
      }
    }

    return thresholdedImage;
  }

  void _applyEdgeDetection() {
    if (_selectedImageData == null) return;

    img.Image image = img.decodeImage(_selectedImageData!)!;

    List<String> coordinateSets = _coordinatesController.text.trim().split('\n');

    for (String coordinateSet in coordinateSets) {
      List<String> parts = coordinateSet.split(' ');
      int pieceNumber = int.parse(parts[0]);
      double centerX = double.parse(parts[1]);
      double centerY = double.parse(parts[2]);
      double width = double.parse(parts[3]);
      double height = double.parse(parts[4]);

      double startX = centerX - width / 2;
      double startY = centerY - height / 2;

      int rectX = (startX * image.width).toInt();
      int rectY = (startY * image.height).toInt();
      int rectWidth = (width * image.width).toInt();
      int rectHeight = (height * image.height).toInt();

      rectX = (rectX + rectWidth * 0.05).toInt();
      rectY = (rectY + rectHeight * 0.05).toInt();
      rectWidth = (rectWidth * 0.9).toInt();
      rectHeight = (rectHeight * 0.9).toInt();

      img.Image croppedImage = img.copyCrop(image, rectX, rectY, rectWidth, rectHeight);

      img.Image thresholdedImage = _applyThreshold(croppedImage, 128);
      img.Image edgeDetectedImage = img.sobel(thresholdedImage);

      List<Offset> contour = _findLargestContour(edgeDetectedImage);

      if (contour.isNotEmpty) {
        _drawContour(image, contour, rectX, rectY);
        Color averageColor = _calculateAverageColorInsideContour(image, contour, rectX, rectY);
        _drawColorOnPiece(image, pieceNumber, averageColor, rectX, rectY, rectWidth, rectHeight);
      }
    }

    _edgeDetectedImageData = Uint8List.fromList(img.encodePng(image));

    setState(() {});
  }

  List<Offset> _findLargestContour(img.Image edgeDetectedImage) {
    int maxArea = 0;
    List<Offset>? largestContour;

    for (int y = 0; y < edgeDetectedImage.height; y++) {
      for (int x = 0; x < edgeDetectedImage.width; x++) {
        int pixel = edgeDetectedImage.getPixel(x, y);
        if (img.getLuminance(pixel) > 0) {
          List<Offset> contour = _traceContour(edgeDetectedImage, x, y);
          if (contour.isNotEmpty) {
            int area = contour.length;
            if (area > 100) {
              if (area > maxArea) {
                maxArea = area;
                largestContour = contour;
              }
            }
          }
        }
      }
    }

    return largestContour ?? [];
  }

  List<Offset> _traceContour(img.Image image, int startX, int startY) {
    int x = startX;
    int y = startY;
    int dir = 0;
    List<Offset> contour = [];

    do {
      if (x >= 0 && x < image.width && y >= 0 && y < image.height) {
        contour.add(Offset(x.toDouble(), y.toDouble()));

        if (img.getLuminance(image.getPixel(x, y)) > 0) {
          image.setPixel(x, y, img.getColor(255, 0, 0, 255));
          dir = (dir + 3) % 4;
        } else {
          dir = (dir + 1) % 4;
        }
      } else {
        break;
      }

      switch (dir) {
        case 0: x += 1; break;
        case 1: y += 1; break;
        case 2: x -= 1; break;
        case 3: y -= 1; break;
      }

    } while ((x != startX || y != startY) && contour.length < 10000);

    return contour;
  }

  void _drawContour(img.Image image, List<Offset> contour, int offsetX, int offsetY) {
    int transparentColor = img.getColor(0, 0, 0, 0);

    for (int i = 0; i < contour.length - 1; i++) {
      _drawLine(
        image,
        Offset(contour[i].dx + offsetX, contour[i].dy + offsetY),
        Offset(contour[i + 1].dx + offsetX, contour[i + 1].dy + offsetY),
        transparentColor,
      );
    }

    _drawLine(
      image,
      Offset(contour.last.dx + offsetX, contour.last.dy + offsetY),
      Offset(contour.first.dx + offsetX, contour.first.dy + offsetY),
      transparentColor,
    );
  }

  void _drawLine(img.Image image, Offset p1, Offset p2, int color) {
    int x0 = p1.dx.toInt();
    int y0 = p1.dy.toInt();
    int x1 = p2.dx.toInt();
    int y1 = p2.dy.toInt();

    int dx = (x1 - x0).abs();
    int dy = (y1 - y0).abs();
    int sx = x0 < x1 ? 1 : -1;
    int sy = y0 < y1 ? 1 : -1;
    int err = dx - dy;

    while (true) {
      image.setPixel(x0, y0, color);
      if (x0 == x1 && y0 == y1) break;
      int e2 = 2 * err;
      if (e2 > -dy) {
        err -= dy;
        x0 += sx;
      }
      if (e2 < dx) {
        err += dx;
        y0 += sy;
      }
    }
  }

  Color _calculateAverageColorInsideContour(img.Image image, List<Offset> contour, int offsetX, int offsetY) {
    int redSum = 0;
    int greenSum = 0;
    int blueSum = 0;
    int pixelCount = 0;

    Set<Offset> visitedPoints = {};
    Set<Offset> contourPoints = contour.toSet();

    double minX = double.infinity;
    double minY = double.infinity;
    double maxX = double.negativeInfinity;
    double maxY = double.negativeInfinity;

    for (Offset point in contour) {
      minX = min(minX, point.dx);
      minY = min(minY, point.dy);
      maxX = max(maxX, point.dx);
      maxY = max(maxY, point.dy);
    }

    for (int y = minY.toInt(); y <= maxY.toInt(); y++) {
      for (int x = minX.toInt(); x <= maxX.toInt(); x++) {
        Offset currentPoint = Offset(x.toDouble(), y.toDouble());

        if (_isPointInsideContour(currentPoint, contour) && !visitedPoints.contains(currentPoint)) {
          visitedPoints.add(currentPoint);

          if (contourPoints.contains(currentPoint)) {
            continue;
          }

          int pixel = image.getPixel(x + offsetX, y + offsetY);
          redSum += img.getRed(pixel);
          greenSum += img.getGreen(pixel);
          blueSum += img.getBlue(pixel);
          pixelCount++;
        }
      }
    }

    if (pixelCount == 0) return Colors.grey;

    int avgRed = (redSum / pixelCount).round();
    int avgGreen = (greenSum / pixelCount).round();
    int avgBlue = (blueSum / pixelCount).round();

    double brightnessFactor = 1.2;

    avgRed = (avgRed * brightnessFactor).clamp(0, 255).toInt();
    avgGreen = (avgGreen * brightnessFactor).clamp(0, 255).toInt();
    avgBlue = (avgBlue * brightnessFactor).clamp(0, 255).toInt();

    return Color.fromRGBO(avgRed, avgGreen, avgBlue, 1.0);
  }

  bool _isPointInsideContour(Offset point, List<Offset> contour) {
    int intersectCount = 0;
    for (int i = 0; i < contour.length; i++) {
      Offset p1 = contour[i];
      Offset p2 = contour[(i + 1) % contour.length];

      if ((p1.dy > point.dy) != (p2.dy > point.dy)) {
        double slope = (point.dy - p1.dy) / (p2.dy - p1.dy);
        if (point.dx < p1.dx + slope * (p2.dx - p1.dx)) {
          intersectCount++;
        }
      }
    }
    return (intersectCount % 2) != 0;
  }

  void _drawColorOnPiece(img.Image image, int pieceNumber, Color color, int x, int y, int width, int height) {
    img.fillRect(image, x + width ~/ 4, y + height ~/ 4, x + width * 3 ~/ 4, y + height * 3 ~/ 4, img.getColor(color.red, color.green, color.blue));

    img.drawString(image, img.arial_24, x + width ~/ 2, y + height ~/ 2, '$pieceNumber', color: img.getColor(0, 0, 0));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Image Square Drawer with Edge Detection')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            if (_selectedImageData == null)
              ElevatedButton(
                onPressed: _pickImageWeb,
                child: Text('Select Image'),
              )
            else
              Column(
                children: [
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Stack(
                        alignment: Alignment.center,
                        children: [
                          Image.memory(
                            _selectedImageData!,
                            width: 400,
                            height: 400,
                          ),
                          if (_highlightedRect != null)
                            Positioned(
                              left: _highlightedRect!.left * 400,
                              top: _highlightedRect!.top * 400,
                              child: Container(
                                width: _highlightedRect!.width * 400,
                                height: _highlightedRect!.height * 400,
                                decoration: BoxDecoration(
                                  border: Border.all(color: Colors.red, width: 2),
                                ),
                              ),
                            ),
                        ],
                      ),
                      if (_edgeDetectedImageData != null)
                        Padding(
                          padding: const EdgeInsets.only(left: 20.0),
                          child: Column(
                            children: [
                              Text('Edge Detected Image:'),
                              Image.memory(
                                _edgeDetectedImageData!,
                                width: 400,
                                height: 400,
                              ),
                            ],
                          ),
                        ),
                    ],
                  ),
                  TextField(
                    controller: _coordinatesController,
                    decoration: InputDecoration(
                      hintText: 'Coordinates (e.g., 0.5 0.5 0.2 0.2)',
                    ),
                    maxLines: 5,
                  ),
                  ElevatedButton(
                    onPressed: _applyEdgeDetection,
                    child: Text('Apply Edge Detection'),
                  ),
                  SizedBox(height: 20),
                  if (_color1 != null) ...[
                    Text('Detected Average Color:'),
                    Container(
                      width: 50,
                      height: 50,
                      color: _color1,
                    ),
                    SizedBox(height: 5),
                    Text('Hex: $_color1Hex'),
                    Text('RGB: $_color1RGB'),
                  ],
                ],
              ),
          ],
        ),
      ),
    );
  }
}
Leave a Comment