[mob][photos] Clean up old dart preprocessing methods

This commit is contained in:
laurenspriem
2024-11-08 09:25:00 +05:30
parent 21af6d0070
commit 899bf79460
2 changed files with 7 additions and 189 deletions

View File

@@ -23,15 +23,6 @@ final _logger = Logger("ImageMlUtil");
/// These are 8 bit unsigned integers in range 0-255 for each RGB channel
typedef RGB = (int, int, int);
const gaussianKernelSize = 5;
const gaussianKernelRadius = gaussianKernelSize ~/ 2;
const gaussianSigma = 10.0;
final List<List<double>> gaussianKernel =
create2DGaussianKernel(gaussianKernelSize, gaussianSigma);
const maxKernelSize = gaussianKernelSize;
const maxKernelRadius = maxKernelSize ~/ 2;
const List<String> supportedRustImageFormats = [
'bmp',
'dds',
@@ -201,45 +192,6 @@ Future<List<Uint8List>> generateFaceThumbnailsUsingCanvas(
}
}
Future<(Float32List, Dimensions)> preprocessImageYoloFace(
Dimensions image,
Uint8List rawRgbaBytes,
) async {
const requiredWidth = 640;
const requiredHeight = 640;
final scale = min(requiredWidth / image.width, requiredHeight / image.height);
final scaledWidth = (image.width * scale).round().clamp(0, requiredWidth);
final scaledHeight = (image.height * scale).round().clamp(0, requiredHeight);
final processedBytes = Float32List(3 * requiredHeight * requiredWidth);
final buffer = Float32List.view(processedBytes.buffer);
int pixelIndex = 0;
const int channelOffsetGreen = requiredHeight * requiredWidth;
const int channelOffsetBlue = 2 * requiredHeight * requiredWidth;
for (var h = 0; h < requiredHeight; h++) {
for (var w = 0; w < requiredWidth; w++) {
late RGB pixel;
if (w >= scaledWidth || h >= scaledHeight) {
pixel = const (114, 114, 114);
} else {
pixel = _getPixelBilinear(
w / scale,
h / scale,
image,
rawRgbaBytes,
);
}
buffer[pixelIndex] = pixel.$1 / 255;
buffer[pixelIndex + channelOffsetGreen] = pixel.$2 / 255;
buffer[pixelIndex + channelOffsetBlue] = pixel.$3 / 255;
pixelIndex++;
}
}
return (processedBytes, Dimensions(width: scaledWidth, height: scaledHeight));
}
Future<Float32List> resizedToPreprocessedYoloFace(
Uint8List rgbBytes,
int rgbWidth,
@@ -309,44 +261,6 @@ Future<Float32List> resizedToPreprocessedClip(
return processedBytes;
}
Future<Float32List> preprocessImageClip(
Dimensions image,
Uint8List rawRgbaBytes,
) async {
const int requiredWidth = 256;
const int requiredHeight = 256;
const int requiredSize = 3 * requiredWidth * requiredHeight;
final scale = max(requiredWidth / image.width, requiredHeight / image.height);
final bool useAntiAlias = scale < 0.8;
final scaledWidth = (image.width * scale).round();
final scaledHeight = (image.height * scale).round();
final widthOffset = max(0, scaledWidth - requiredWidth) / 2;
final heightOffset = max(0, scaledHeight - requiredHeight) / 2;
final processedBytes = Float32List(requiredSize);
final buffer = Float32List.view(processedBytes.buffer);
int pixelIndex = 0;
const int greenOff = requiredHeight * requiredWidth;
const int blueOff = 2 * requiredHeight * requiredWidth;
for (var h = 0 + heightOffset; h < scaledHeight - heightOffset; h++) {
for (var w = 0 + widthOffset; w < scaledWidth - widthOffset; w++) {
final RGB pixel = _getPixelBilinear(
w / scale,
h / scale,
image,
rawRgbaBytes,
antiAlias: useAntiAlias,
);
buffer[pixelIndex] = pixel.$1 / 255;
buffer[pixelIndex + greenOff] = pixel.$2 / 255;
buffer[pixelIndex + blueOff] = pixel.$3 / 255;
pixelIndex++;
}
}
return processedBytes;
}
Future<(Float32List, List<AlignmentResult>, List<bool>, List<double>, Size)>
preprocessToMobileFaceNetFloat32List(
Dimensions imageDimensions,
@@ -424,10 +338,10 @@ RGB _readPixelColor(
Uint8List rgbaBytes,
) {
if (y < 0 || y >= image.height || x < 0 || x >= image.width) {
if (y < -maxKernelRadius ||
y >= image.height + maxKernelRadius ||
x < -maxKernelRadius ||
x >= image.width + maxKernelRadius) {
if (y < -2 ||
y >= image.height + 2 ||
x < -2 ||
x >= image.width + 2) {
_logger.severe(
'`readPixelColor`: Invalid pixel coordinates, out of bounds. x: $x, y: $y',
);
@@ -445,29 +359,6 @@ RGB _readPixelColor(
);
}
RGB _getPixelBlurred(
int x,
int y,
Dimensions image,
Uint8List rgbaBytes,
) {
double r = 0, g = 0, b = 0;
for (int ky = 0; ky < gaussianKernelSize; ky++) {
for (int kx = 0; kx < gaussianKernelSize; kx++) {
final int px = (x - gaussianKernelRadius + kx);
final int py = (y - gaussianKernelRadius + ky);
final RGB pixelRgbTuple = _readPixelColor(px, py, image, rgbaBytes);
final double weight = gaussianKernel[ky][kx];
r += pixelRgbTuple.$1 * weight;
g += pixelRgbTuple.$2 * weight;
b += pixelRgbTuple.$3 * weight;
}
}
return (r.round(), g.round(), b.round());
}
List<List<int>> _createGrayscaleIntMatrixFromNormalized2List(
Float32List imageList,
int startIndex, {
@@ -615,52 +506,6 @@ Future<Uint8List> _cropAndEncodeCanvas(
return await _encodeImageToPng(croppedImage);
}
RGB _getPixelBilinear(
num fx,
num fy,
Dimensions image,
Uint8List rawRgbaBytes, {
bool antiAlias = false,
}) {
// Clamp to image boundaries
fx = fx.clamp(0, image.width - 1);
fy = fy.clamp(0, image.height - 1);
// Get the surrounding coordinates and their weights
final int x0 = fx.floor();
final int x1 = fx.ceil();
final int y0 = fy.floor();
final int y1 = fy.ceil();
final dx = fx - x0;
final dy = fy - y0;
final dx1 = 1.0 - dx;
final dy1 = 1.0 - dy;
// Get the original pixels (with gaussian blur if antialias)
final RGB Function(int, int, Dimensions, Uint8List) readPixel =
antiAlias ? _getPixelBlurred : _readPixelColor;
final RGB pixel1 = readPixel(x0, y0, image, rawRgbaBytes);
final RGB pixel2 = readPixel(x1, y0, image, rawRgbaBytes);
final RGB pixel3 = readPixel(x0, y1, image, rawRgbaBytes);
final RGB pixel4 = readPixel(x1, y1, image, rawRgbaBytes);
int bilinear(
num val1,
num val2,
num val3,
num val4,
) =>
(val1 * dx1 * dy1 + val2 * dx * dy1 + val3 * dx1 * dy + val4 * dx * dy)
.round();
// Calculate the weighted sum of pixels
final int r = bilinear(pixel1.$1, pixel2.$1, pixel3.$1, pixel4.$1);
final int g = bilinear(pixel1.$2, pixel2.$2, pixel3.$2, pixel4.$2);
final int b = bilinear(pixel1.$3, pixel2.$3, pixel3.$3, pixel4.$3);
return (r, g, b);
}
/// Get the pixel value using Bicubic Interpolation. Code taken mainly from https://github.com/brendan-duncan/image/blob/6e407612752ffdb90b28cd5863c7f65856349348/lib/src/image/image.dart#L697
RGB _getPixelBicubic(
num fx,
@@ -763,31 +608,4 @@ RGB _getPixelBicubic(
// final c3 = cubic(dy, ip3, ic3, in3, ia3);
return (c0, c1, c2); // (red, green, blue)
}
List<List<double>> create2DGaussianKernel(int size, double sigma) {
final List<List<double>> kernel =
List.generate(size, (_) => List<double>.filled(size, 0));
double sum = 0.0;
final int center = size ~/ 2;
for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
final int dx = x - center;
final int dy = y - center;
final double g = (1 / (2 * pi * sigma * sigma)) *
exp(-(dx * dx + dy * dy) / (2 * sigma * sigma));
kernel[y][x] = g;
sum += g;
}
}
// Normalize the kernel
for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
kernel[y][x] /= sum;
}
}
return kernel;
}
}

View File

@@ -415,9 +415,9 @@ Future<MLResult> analyzeImageStatic(Map args) async {
if (decodeInRust) {
rustResults = await processImageMlFromPath(imagePath: imagePath);
} else {
final (image, rawRgbaBytes) = await decodeImageFromPath(imagePath);
final (image, decodedRgbaBytes) = await decodeImageFromPath(imagePath);
rustResults = await processImageMlFromData(
rgbaData: rawRgbaBytes,
rgbaData: decodedRgbaBytes,
width: image.width,
height: image.height,
);