mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-27 21:02:35 +00:00
Merge branch 'alternate_binarizer'
This commit is contained in:
@@ -60,3 +60,6 @@ experimental_features = []
|
|||||||
|
|
||||||
#/// Adds support for serde Serialize and Deserialize for outward facing structs
|
#/// Adds support for serde Serialize and Deserialize for outward facing structs
|
||||||
serde = ["dep:serde"]
|
serde = ["dep:serde"]
|
||||||
|
|
||||||
|
#/// Adds otsu binarizer support using imageproc
|
||||||
|
otsu_level = ["image"]
|
||||||
@@ -709,6 +709,22 @@ impl fmt::Display for BitMatrix {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "image")]
|
||||||
|
/// This should only be used if you *know* that the `DynamicImage` is binary.
|
||||||
|
impl TryFrom<image::DynamicImage> for BitMatrix {
|
||||||
|
type Error = Exceptions;
|
||||||
|
|
||||||
|
fn try_from(value: image::DynamicImage) -> Result<Self, Self::Error> {
|
||||||
|
let mut new_bitmatrix = BitMatrix::new(value.width(), value.height())?;
|
||||||
|
for (x, y, value) in value.as_luma8().unwrap().enumerate_pixels() {
|
||||||
|
if value.0[0] != u8::MAX {
|
||||||
|
new_bitmatrix.set(x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(new_bitmatrix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "image")]
|
#[cfg(feature = "image")]
|
||||||
impl From<BitMatrix> for image::DynamicImage {
|
impl From<BitMatrix> for image::DynamicImage {
|
||||||
fn from(value: BitMatrix) -> Self {
|
fn from(value: BitMatrix) -> Self {
|
||||||
|
|||||||
@@ -103,3 +103,8 @@ pub use global_histogram_binarizer::*;
|
|||||||
|
|
||||||
mod hybrid_binarizer;
|
mod hybrid_binarizer;
|
||||||
pub use hybrid_binarizer::*;
|
pub use hybrid_binarizer::*;
|
||||||
|
|
||||||
|
#[cfg(feature = "otsu_level")]
|
||||||
|
mod otsu_level_binarizer;
|
||||||
|
#[cfg(feature = "otsu_level")]
|
||||||
|
pub use otsu_level_binarizer::*;
|
||||||
|
|||||||
85
src/common/otsu_level_binarizer.rs
Normal file
85
src/common/otsu_level_binarizer.rs
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
use std::{borrow::Cow, rc::Rc};
|
||||||
|
|
||||||
|
use image::{DynamicImage, ImageBuffer, Luma};
|
||||||
|
use once_cell::sync::OnceCell;
|
||||||
|
|
||||||
|
use crate::{Binarizer, Exceptions, LuminanceSource};
|
||||||
|
|
||||||
|
use super::{BitArray, BitMatrix};
|
||||||
|
|
||||||
|
pub struct OtsuLevelBinarizer {
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
source: Box<dyn LuminanceSource>,
|
||||||
|
black_matrix: OnceCell<BitMatrix>,
|
||||||
|
black_row_cache: Vec<OnceCell<BitArray>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OtsuLevelBinarizer {
|
||||||
|
fn generate_threshold_matrix(source: &dyn LuminanceSource) -> Result<BitMatrix, Exceptions> {
|
||||||
|
let image_buffer = {
|
||||||
|
let Some(buff) : Option<ImageBuffer<Luma<u8>,Vec<u8>>> = ImageBuffer::from_vec(source.getWidth() as u32, source.getHeight() as u32, source.getMatrix()) else {
|
||||||
|
return Err(Exceptions::IllegalArgumentException(None))
|
||||||
|
};
|
||||||
|
buff
|
||||||
|
};
|
||||||
|
|
||||||
|
let otsu_level = imageproc::contrast::otsu_level(&image_buffer);
|
||||||
|
|
||||||
|
let filtered_iamge = imageproc::contrast::threshold(&image_buffer, otsu_level);
|
||||||
|
|
||||||
|
let dynamic_filtered = DynamicImage::from(filtered_iamge);
|
||||||
|
|
||||||
|
dynamic_filtered.try_into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(source: Box<dyn LuminanceSource>) -> Self {
|
||||||
|
Self {
|
||||||
|
width: source.getWidth(),
|
||||||
|
height: source.getHeight(),
|
||||||
|
black_row_cache: vec![OnceCell::default(); source.getHeight()],
|
||||||
|
source,
|
||||||
|
black_matrix: OnceCell::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Binarizer for OtsuLevelBinarizer {
|
||||||
|
fn getLuminanceSource(&self) -> &Box<dyn crate::LuminanceSource> {
|
||||||
|
&self.source
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getBlackRow(
|
||||||
|
&self,
|
||||||
|
y: usize,
|
||||||
|
) -> Result<std::borrow::Cow<super::BitArray>, crate::Exceptions> {
|
||||||
|
let row = self.black_row_cache[y].get_or_try_init(|| {
|
||||||
|
let matrix = self.getBlackMatrix()?;
|
||||||
|
Ok(matrix.getRow(y as u32))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(Cow::Borrowed(row))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getBlackMatrix(&self) -> Result<&super::BitMatrix, crate::Exceptions> {
|
||||||
|
let matrix = self
|
||||||
|
.black_matrix
|
||||||
|
.get_or_try_init(|| Self::generate_threshold_matrix(self.source.as_ref()))?;
|
||||||
|
Ok(matrix)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn createBinarizer(
|
||||||
|
&self,
|
||||||
|
source: Box<dyn crate::LuminanceSource>,
|
||||||
|
) -> std::rc::Rc<dyn Binarizer> {
|
||||||
|
Rc::new(Self::new(source))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getWidth(&self) -> usize {
|
||||||
|
self.width
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getHeight(&self) -> usize {
|
||||||
|
self.height
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
//package com.google.zxing;
|
//package com.google.zxing;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
use crate::Exceptions;
|
use crate::Exceptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user