GrainPestCNN โ€” On-Device Acoustic Pest Classifier for Google AI Edge

An ultra-compact (~240K parameters), NPU-optimized acoustic classification model designed for real-time, on-device detection of stored-grain insects (Rhyzopertha dominica / Lesser Grain Borer vs. Sitophilus oryzae / Rice Weevil).

This model is engineered specifically for Google AI Edge / LiteRT, MediaPipe, and Qualcomm Hexagon NPU deployment. It uses only NPU-friendly operations (Conv2d, BatchNorm, ReLU, AdaptiveAvgPool) with a fixed (1, 1, 64, 1000) tensor input.


Model Architecture & Specs

Property Value
Architecture GrainPestCNN (4-stage strided conv blocks + global pooling)
Parameters 240,866 (~950 KB FP32, ~240 KB INT8)
Primary Framework Google AI Edge (LiteRT / TFLite), ONNX, PyTorch
Input Shape (1, 1, 64, 1000) (Batch, Channels, Mel Bins, Frames)
Audio Input 10 seconds mono WAV, 16 kHz sample rate
Target Classes lesser_grain_borer, rice_weevil
Test Accuracy 95.0%
Test Macro F1 0.950
Target Hardware Google AI Edge, Android (LiteRT / MediaPipe), Qualcomm Hexagon NPU

Files in this Repository

  • grainpest_cnn.tflite / grainpest_cnn_int8.tflite: Google AI Edge / LiteRT models for mobile on-device inference.
  • grainpest_cnn.onnx: ONNX export (opset 13) for cross-platform desktop/server inference.
  • grainpest_cnn.ts.pt: TorchScript traced module.
  • cnn.pt: PyTorch model checkpoint (state_dict, class names, architecture width).
  • config.json: Hardware target, audio frontend parameters, and tensor dimensions.
  • labels.json: Class ID to name dictionary.
  • labels.txt: Line-delimited labels for TFLite / MediaPipe tasks.

Audio Preprocessing Pipeline

The model expects log-mel spectrogram features computed from a 10-second audio clip:

  1. Audio Resampling: Resample input to 16,000 Hz mono.
  2. Windowing: Fixed 10.0 seconds (160,000 samples). Pad with zeros if shorter, center-crop if longer.
  3. Mel Spectrogram:
    • n_fft: 400 (25 ms)
    • hop_length: 160 (10 ms)
    • n_mels: 64 bins
    • f_min: 50 Hz, f_max: 8,000 Hz
  4. Log Compression: Amplitude to dB (top_db = 80).
  5. Frame Alignment: Exactly 1,000 frames (shape 1 x 64 x 1000).

Quickstart: Python Inference

Using LiteRT / TFLite Runtime

import numpy as np

# Load LiteRT / TFLite interpreter
try:
    import ai_edge_litert.interpreter as litert
    interpreter = litert.Interpreter(model_path="grainpest_cnn.tflite")
except ImportError:
    import tensorflow.lite as tflite
    interpreter = tflite.Interpreter(model_path="grainpest_cnn.tflite")

interpreter.allocate_tensors()
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()

# mel_spectrogram shape: (1, 1, 64, 1000)
sample_mel = np.zeros((1, 1, 64, 1000), dtype=np.float32)

interpreter.set_tensor(input_details[0]["index"], sample_mel)
interpreter.invoke()
logits = interpreter.get_tensor(output_details[0]["index"])

labels = ["lesser_grain_borer", "rice_weevil"]
predicted_class = labels[np.argmax(logits)]
print(f"Prediction: {predicted_class}")

Using ONNX Runtime

import onnxruntime as ort
import numpy as np

session = ort.InferenceSession("grainpest_cnn.onnx")
sample_mel = np.zeros((1, 1, 64, 1000), dtype=np.float32)
outputs = session.run(["logits"], {"mel": sample_mel})
labels = ["lesser_grain_borer", "rice_weevil"]
print("Prediction:", labels[np.argmax(outputs[0])])

On-Device Deployment: Google AI Edge / Android

1. Google AI Edge Gallery Integration

To allow the Google AI Edge Gallery application to download and execute this model on Android or iOS, add the following entry to model_allowlist.json:

{
  "name": "Grain Pest Acoustic Classifier",
  "modelId": "YOUR_HF_USERNAME/grainpest-classifier-litert",
  "modelFile": "grainpest_cnn_int8.tflite",
  "taskType": "AUDIO_CLASSIFICATION",
  "sizeInBytes": 245000,
  "description": "NPU-accelerated bioacoustic detection of grain-damaging weevils and borers"
}

2. Standalone Android LiteRT (Kotlin)

import com.google.ai.edge.litert.Interpreter
import java.nio.ByteBuffer

// Initialize LiteRT with Qualcomm Hexagon / NPU accelerator delegate
val options = Interpreter.Options().apply {
    setNumThreads(4)
    // Add NPU or NNAPI acceleration if available:
    // addDelegate(NpuDelegate())
}

val interpreter = Interpreter(loadModelFile("grainpest_cnn_int8.tflite"), options)

// Input tensor: 1 x 1 x 64 x 1000 (Float32 or quantized)
val inputBuffer: ByteBuffer = prepareMelSpectrogram(audioRecording)
val outputBuffer: ByteBuffer = ByteBuffer.allocateDirect(2 * 4) // 2 float logits

interpreter.run(inputBuffer, outputBuffer)

Citation & License

  • License: Apache 2.0
  • Dataset: Bioacoustic Stored-Grain Pest Dataset (IRRI Sensor Archive)
Downloads last month
-
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support