Untitled
unknown
plain_text
a month ago
21 kB
1
Indexable
Never
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