clustering
This commit is contained in:
@@ -11,6 +11,4 @@ image = "0.25.6"
|
|||||||
show-image = "0.14.1"
|
show-image = "0.14.1"
|
||||||
rand = "0.9.1"
|
rand = "0.9.1"
|
||||||
rayon = "1.10.0"
|
rayon = "1.10.0"
|
||||||
linfa = "0.7.1"
|
hdbscan = "0.10.0"
|
||||||
linfa-clustering = "0.7.1"
|
|
||||||
ndarray = "0.16.1"
|
|
||||||
53
src/main.rs
53
src/main.rs
@@ -1,20 +1,15 @@
|
|||||||
use linfa::traits::Transformer;
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
use std::iter::zip;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use image::{DynamicImage, ImageReader, Rgb};
|
use hdbscan::{Hdbscan, HdbscanHyperParams};
|
||||||
use linfa_clustering::Dbscan;
|
use image::{DynamicImage, ImageReader, Rgb, RgbImage};
|
||||||
use rand::{Rng};
|
use rand::{Rng};
|
||||||
use show_image::{create_window, ImageInfo, ImageView, PixelFormat};
|
use show_image::{create_window, ImageInfo, ImageView, PixelFormat};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use ndarray::{Array2, Axis};
|
|
||||||
|
|
||||||
use linfa::prelude::*;
|
fn extract_highlights_and_distort(image: &Vec<u8>, width: u32, threshold: u8, downsample: f64) -> Vec<Vec<f64>> {
|
||||||
// We'll build our dataset on our own using ndarray and rand
|
|
||||||
use ndarray::prelude::*;
|
|
||||||
|
|
||||||
|
|
||||||
fn extract_highlights(image: &Vec<u8>, width: u32, threshold: u8, downsample: f64) -> Array2<u32> {
|
|
||||||
let max_rng = (u32::MAX as f64 * downsample) as u32;
|
let max_rng = (u32::MAX as f64 * downsample) as u32;
|
||||||
|
let width_2 = width as f64 / 2.0;
|
||||||
let poi = image
|
let poi = image
|
||||||
.par_iter()
|
.par_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
@@ -23,11 +18,13 @@ fn extract_highlights(image: &Vec<u8>, width: u32, threshold: u8, downsample: f6
|
|||||||
let mut rng = rand::rng();
|
let mut rng = rand::rng();
|
||||||
rng.random::<u32>() < max_rng
|
rng.random::<u32>() < max_rng
|
||||||
})
|
})
|
||||||
.map(move |(i, _)| [ i as u32 % width, i as u32 / width ]);
|
.map(move |(i, _)| {
|
||||||
|
vec![ i as f64 % width as f64 - width_2, i as f64 / width as f64 ]
|
||||||
|
});
|
||||||
|
|
||||||
let mut vec = Vec::new();
|
let mut vec = Vec::new();
|
||||||
vec.par_extend(poi);
|
vec.par_extend(poi);
|
||||||
Array2::from(vec)
|
vec
|
||||||
}
|
}
|
||||||
|
|
||||||
#[show_image::main]
|
#[show_image::main]
|
||||||
@@ -40,15 +37,39 @@ fn main() {
|
|||||||
|
|
||||||
let window = create_window("image", Default::default()).unwrap();
|
let window = create_window("image", Default::default()).unwrap();
|
||||||
let mut t: VecDeque<Duration> = VecDeque::with_capacity(25);
|
let mut t: VecDeque<Duration> = VecDeque::with_capacity(25);
|
||||||
|
let params = HdbscanHyperParams::builder()
|
||||||
|
.epsilon(5.0)
|
||||||
|
.min_samples(5)
|
||||||
|
.min_cluster_size(100)
|
||||||
|
.build();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let poi = extract_highlights(&img_data, width, 196, 1.0);
|
let poi = extract_highlights_and_distort(&img_data, width, 196, 0.05);
|
||||||
|
|
||||||
let mut rgb_image = img.to_rgb8();
|
let clusterer = Hdbscan::new(&poi, params.clone());
|
||||||
|
let labels = clusterer.cluster().unwrap();
|
||||||
|
|
||||||
|
let mut rgb_image = RgbImage::new(width, height);
|
||||||
|
|
||||||
poi.outer_iter().for_each(|pixel| {
|
zip(poi, labels).for_each(|(pixel, label)| {
|
||||||
rgb_image.put_pixel(pixel[0], pixel[1], Rgb([255, 0, 0]))
|
if label != -1 {
|
||||||
|
let color = vec![Rgb([255, 0, 0]), Rgb([0, 255, 0]), Rgb([0, 0, 255]), Rgb([0, 0, 0])][label as usize];
|
||||||
|
let x = (pixel[0] + width as f64 / 2.0) as u32;
|
||||||
|
rgb_image.put_pixel(x, pixel[1] as u32, color);
|
||||||
|
if pixel[0] > 0.0 {
|
||||||
|
rgb_image.put_pixel(x - 1, pixel[1] as u32, color);
|
||||||
|
}
|
||||||
|
if pixel[0] < width as f64 - 1.0 {
|
||||||
|
rgb_image.put_pixel(x + 1, pixel[1] as u32, color);
|
||||||
|
}
|
||||||
|
if pixel[1] > 0.0 {
|
||||||
|
rgb_image.put_pixel(x, pixel[1] as u32 - 1, color);
|
||||||
|
}
|
||||||
|
if pixel[1] < height as f64 - 1.0 {
|
||||||
|
rgb_image.put_pixel(x, pixel[1] as u32 + 1, Rgb([label as u8 * 8, 0, 0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let image = ImageView::new(ImageInfo::new(PixelFormat::Rgb8, width, height), rgb_image.iter().as_slice());
|
let image = ImageView::new(ImageInfo::new(PixelFormat::Rgb8, width, height), rgb_image.iter().as_slice());
|
||||||
|
|||||||
Reference in New Issue
Block a user