Skip to content

Commit d81a44e

Browse files
author
harunlakodla
committed
all about files update
1 parent fba13b0 commit d81a44e

12 files changed

+265
-27
lines changed

README.md

+8-13
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,28 @@ know whether this package might be useful for them.
66
TODO:
77

88
- [ ] Image Reading and Writing:
9-
- [ ] Read image: `imread()`
10-
- [ ] Write image: `imwrite()`
9+
- [X] Read image: `imread()`
10+
- [X] Write image: `imwrite()`
1111

1212
- [ ] Image Properties:
13-
- [ ] Get image size: `size()`
13+
- [X] Get image size: `size()`
1414
- [ ] Determine image type: `type()`
1515
- [ ] Access and modify pixel values on the image: `at()`, `set()`
1616

1717
- [ ] Color Conversions:
18-
- [ ] Convert color spaces: `cvtColor()`
18+
- [X] Convert color spaces: `cvtColor()` for grayscale
1919
- [ ] Define constants for color space conversions: `COLOR_*`
2020

2121
- [ ] Filtering and Edge Detection:
22-
- [ ] Gaussian blur: `GaussianBlur()`
22+
- [X] Gaussian blur: `GaussianBlur()`
2323
- [ ] Median blur: `medianBlur()`
24-
- [ ] Edge detection: `Canny()`
24+
- [X] Edge detection: `Canny()`
2525
- [ ] Histogram equalization: `equalizeHist()`
2626

2727
- [ ] Geometric Transformations:
2828
- [ ] Perspective transformation: `warpPerspective()`
29-
- [ ] Scaling: `resize()`
30-
- [ ] Rotation: `rotate()`
29+
- [X] Scaling: `resize()`
30+
- [X] Rotation: `rotate()`
3131

3232
- [ ] Template Matching:
3333
- [ ] Template matching operation: `matchTemplate()`
@@ -54,11 +54,6 @@ TODO:
5454
- [ ] Detect keyboard or mouse interactions: `waitKey()`
5555

5656

57-
## Getting started
58-
59-
TODO: List prerequisites and provide or point to information on how to
60-
start using the package.
61-
6257
## Usage
6358

6459
TODO: Include short and useful examples for package users. Add longer examples

example/dart_opencv_sdk_example.dart

+6-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,16 @@ void main() async {
77
..decodeWebPFile('test.webp')
88
// Resize the image so its width is 120 and height maintains aspect
99
// ratio.
10-
..copyResize(width: 1200)
10+
..copyResize(width: 240)
11+
..copyRotate(angle: 5)
12+
..grayscale()
1113
// ..grayscale()
1214
..drawCircle(
1315
x: 20, y: 50, radius: 50, color: img.ColorFloat16.rgb(255, 0, 0))
1416
// Save the image to a PNG file.
15-
..writeToFile('thumbnail_normalize.png'))
17+
..writeToFile('thumbnail_rotate.png'))
1618
// Execute the image commands in an isolate thread
1719
.executeThread();
20+
21+
1822
}

example/thumbnail_rotate.png

79.2 KB
Loading

lib/src/core/functions.dart

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:image/image.dart';
22

33
class CoreFunctions {
4+
45
int getRed(int color) {
56
return (color >> 16) & 0xFF;
67
}

lib/src/edge_detector/canny_edge.dart

+179
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
import 'package:dart_opencv_sdk/src/filter/grayscale.dart';
2+
import 'package:image/image.dart';
3+
4+
import '../core/functions.dart';
5+
import '../smoothing/guassian.dart';
6+
import '../filter/filter.dart';
7+
import 'dart:math';
8+
9+
class CannyEdgeFilter implements ImageFilter {
10+
final CoreFunctions coreFunctions;
11+
final double lowThreshold;
12+
final double highThreshold;
13+
final int kernelSize;
14+
final double sigma;
15+
16+
CannyEdgeFilter({
17+
this.lowThreshold = 20,
18+
this.highThreshold = 50,
19+
this.kernelSize = 3,
20+
this.sigma = 1.4,
21+
}) : coreFunctions = CoreFunctions();
22+
23+
@override
24+
Image applyFilter(Image image) {
25+
final grayscaleImage = GrayscaleFilter().applyFilter(image);
26+
final blurredImage =
27+
GaussianBlurFilter(sigma: sigma, radius: kernelSize ~/ 2)
28+
.applyFilter(grayscaleImage);
29+
final gradients = calculateGradients(blurredImage);
30+
final suppressedImage = applyNonMaximaSuppression(blurredImage, gradients);
31+
final thresholdedImage =
32+
applyDoubleThreshold(suppressedImage, lowThreshold, highThreshold);
33+
final edgeImage = applyEdgeTrackingByHysteresis(thresholdedImage);
34+
35+
return edgeImage;
36+
}
37+
38+
List<List<double>> calculateGradients(Image image) {
39+
final sobelX = [
40+
[-1, 0, 1],
41+
[-2, 0, 2],
42+
[-1, 0, 1],
43+
];
44+
45+
final sobelY = [
46+
[-1, -2, -1],
47+
[0, 0, 0],
48+
[1, 2, 1],
49+
];
50+
51+
final gradients = [[]] as List<List<double>>;
52+
for (var x = 0; x < image.width; x++) {
53+
gradients[x] = [] as List<double>;
54+
for (var y = 0; y < image.height; y++) {
55+
gradients[x][y] = 0;
56+
}
57+
}
58+
59+
for (var y = 1; y < image.height - 1; y++) {
60+
for (var x = 1; x < image.width - 1; x++) {
61+
var gx = 0.0;
62+
var gy = 0.0;
63+
64+
for (var j = -1; j <= 1; j++) {
65+
for (var i = -1; i <= 1; i++) {
66+
final pixel = image.getPixelSafe(x + i, y + j);
67+
final luminance = pixel.r;
68+
gx += sobelX[i + 1][j + 1] * luminance;
69+
gy += sobelY[i + 1][j + 1] * luminance;
70+
}
71+
}
72+
73+
gradients[x][y] = sqrt(gx * gx + gy * gy);
74+
}
75+
}
76+
77+
return gradients;
78+
}
79+
80+
Image applyNonMaximaSuppression(Image image, List<List<double>> gradients) {
81+
final suppressedImage = Image(width: image.width, height: image.height);
82+
83+
for (var y = 1; y < image.height - 1; y++) {
84+
for (var x = 1; x < image.width - 1; x++) {
85+
final pixel = image.getPixel(x, y);
86+
final pixelValue = pixel.r;
87+
88+
final angle = atan2(gradients[x][y], gradients[x - 1][y]);
89+
final direction = (angle * (180 / pi) + 180) % 180;
90+
91+
final neighbor1 = coreFunctions.getPixelSafer(image, x - 1, y);
92+
final neighbor2 = coreFunctions.getPixelSafer(image, x + 1, y);
93+
94+
final neighbor1Value = neighbor1.r;
95+
final neighbor2Value = neighbor2.r;
96+
97+
final interpolatedValue = interpolate(pixelValue.toInt(),
98+
neighbor1Value.toInt(), neighbor2Value.toInt(), direction);
99+
suppressedImage.setPixel(x, y,
100+
getColor(interpolatedValue, interpolatedValue, interpolatedValue));
101+
}
102+
}
103+
104+
return suppressedImage;
105+
}
106+
107+
int interpolate(int center, int neighbor1, int neighbor2, double direction) {
108+
final weight = direction % 45 / 45;
109+
final interpolatedValue =
110+
((1 - weight) * neighbor1 + weight * neighbor2).round();
111+
112+
if (center >= interpolatedValue) {
113+
return center;
114+
} else {
115+
return 0;
116+
}
117+
}
118+
119+
Image applyDoubleThreshold(
120+
Image image, double lowThreshold, double highThreshold) {
121+
final thresholdedImage = Image(width: image.width, height: image.height);
122+
123+
for (var y = 0; y < image.height; y++) {
124+
for (var x = 0; x < image.width; x++) {
125+
final pixel = image.getPixel(x, y);
126+
final pixelValue = pixel.r;
127+
128+
if (pixelValue >= highThreshold) {
129+
thresholdedImage.setPixel(x, y, getColor(255, 255, 255));
130+
} else if (pixelValue >= lowThreshold) {
131+
thresholdedImage.setPixel(x, y, getColor(128, 128, 128));
132+
} else {
133+
thresholdedImage.setPixel(x, y, getColor(0, 0, 0));
134+
}
135+
}
136+
}
137+
138+
return thresholdedImage;
139+
}
140+
141+
Image applyEdgeTrackingByHysteresis(Image image) {
142+
final edgeImage = Image(width: image.width, height: image.height);
143+
144+
for (var y = 1; y < image.height - 1; y++) {
145+
for (var x = 1; x < image.width - 1; x++) {
146+
final pixel = image.getPixel(x, y);
147+
final pixelValue = pixel.r;
148+
149+
if (pixelValue == 128) {
150+
final neighbor1 = coreFunctions.getPixelSafer(image, x - 1, y);
151+
final neighbor2 = coreFunctions.getPixelSafer(image, x + 1, y);
152+
final neighbor3 = coreFunctions.getPixelSafer(image, x, y - 1);
153+
final neighbor4 = coreFunctions.getPixelSafer(image, x, y + 1);
154+
155+
final neighbor1Value = neighbor1.r;
156+
final neighbor2Value = neighbor2.r;
157+
final neighbor3Value = neighbor3.r;
158+
final neighbor4Value = neighbor4.r;
159+
160+
if (neighbor1Value == 255 ||
161+
neighbor2Value == 255 ||
162+
neighbor3Value == 255 ||
163+
neighbor4Value == 255) {
164+
edgeImage.setPixel(x, y, getColor(255, 255, 255));
165+
} else {
166+
edgeImage.setPixel(x, y, getColor(0, 0, 0));
167+
}
168+
} else {
169+
edgeImage.setPixel(x, y, getColor(0, 0, 0));
170+
}
171+
}
172+
}
173+
174+
return edgeImage;
175+
}
176+
177+
@override
178+
dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
179+
}
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import 'package:dart_opencv_sdk/src/core/functions.dart';
2+
import 'package:image/image.dart';
3+
4+
abstract class EdgeDetectorFilter implements Image, CoreFunctions {
5+
Image applyFilter(Image image);
6+
}

lib/src/filter/laplace.dart renamed to lib/src/edge_detector/laplace.dart

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
import 'package:image/image.dart';
22

3-
import 'filter.dart';
4-
3+
import '../core/functions.dart';
4+
import '../filter/filter.dart';
55

66
// https://docs.opencv.org/3.4/d5/db5/tutorial_laplace_operator.html
77
class LaplaceFilter extends ImageFilter {
8+
final CoreFunctions coreFunctions;
89
final List<List<int>> laplaceKernel = [
910
[0, 1, 0],
1011
[1, -4, 1],
1112
[0, 1, 0]
1213
];
1314

15+
LaplaceFilter() : coreFunctions = CoreFunctions();
16+
1417
@override
1518
Image applyFilter(Image image) {
1619
final filteredImage = Image(width: image.width, height: image.height);
@@ -21,7 +24,7 @@ class LaplaceFilter extends ImageFilter {
2124

2225
final filteredPixel = sum.clamp(0, 255).toInt();
2326
final filteredColor =
24-
getColor(filteredPixel, filteredPixel, filteredPixel);
27+
ColorFloat64.rgb(filteredPixel, filteredPixel, filteredPixel);
2528
filteredImage.setPixel(x, y, filteredColor);
2629
}
2730
}
@@ -34,7 +37,7 @@ class LaplaceFilter extends ImageFilter {
3437

3538
for (var ky = -1; ky <= 1; ky++) {
3639
for (var kx = -1; kx <= 1; kx++) {
37-
final pixel = getPixelSafer(image, x + kx, y + ky);
40+
final pixel = coreFunctions.getPixelSafer(image, x + kx, y + ky);
3841
final kernelValue = laplaceKernel[ky + 1][kx + 1];
3942
final r = pixel.r;
4043
final g = pixel.g;

lib/src/filter/filter.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import 'package:dart_opencv_sdk/src/core/functions.dart';
22
import 'package:image/image.dart';
33

4-
abstract class ImageFilter implements Image, CoreFunctions {
4+
abstract class ImageFilter implements Image {
55
Image applyFilter(Image image);
66
}

lib/src/filter/grayscale.dart

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import 'package:image/image.dart';
2+
import 'package:image/src/filter/grayscale.dart';
3+
4+
import '../core/functions.dart';
5+
import 'filter.dart';
6+
7+
class GrayscaleFilter implements ImageFilter {
8+
final CoreFunctions coreFunctions;
9+
10+
GrayscaleFilter() : coreFunctions = CoreFunctions();
11+
// @override
12+
// Image applyFilter(Image image) {
13+
// final grayscaleImage = Image(width: image.width, height: image.height);
14+
15+
// for (var y = 0; y < image.height; y++) {
16+
// for (var x = 0; x < image.width; x++) {
17+
// final pixel = image.getPixel(x, y);
18+
// final r = pixel.r;
19+
// final g = pixel.g;
20+
// final b = pixel.b;
21+
// final luminance = ((0.299 * r) + (0.587 * g) + (0.114 * b)).toInt();
22+
// grayscaleImage.setPixel(
23+
// x, y, getColor(luminance, luminance, luminance));
24+
// }
25+
// }
26+
27+
// return grayscaleImage;
28+
// }
29+
30+
@override
31+
Image applyFilter(Image image) {
32+
Image grayscaleImage = Image(width: image.width, height: image.height);
33+
grayscaleImage = grayscale(image);
34+
return grayscaleImage;
35+
}
36+
37+
@override
38+
dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
39+
}

lib/src/smoothing/averaging.dart

Whitespace-only changes.

0 commit comments

Comments
 (0)