The goal is simple - get the colour at (0, 0) and remove any pixels in the image that are similar to it within the specified threshold (16384 in this case). However, the code below doesn't compile:
#![feature(env, old_path, core, old_io)]
extern crate image;
use std::env;
use std::num::ToPrimitive;
use std::old_io::File;
use image::color::FromColor;
use image::Pixel;
fn get_arguments() -> Vec<String> {
let mut argv: Vec<String> = env::args().collect();
argv.remove(0);
return argv;
}
fn remove_background<T:image::GenericImage>(img: &mut T) {
let background_color = img.get_pixel(0, 0).to_rgba();
let transparent_pixel = image::Rgba([0, 0, 0, 0]);
if background_color[3].to_uint().unwrap() > 0 {
for (x, y, color) in img.pixels() {
let rgba = color.to_rgba();
let (dr,dg,db) = (rgba[0] - background_color[0],
rgba[1] - background_color[1],
rgba[2] - background_color[2]);
if (dr*dr + dg*dg + db*db).to_uint().unwrap() < 16384 { img.put_pixel(x, y, transparent_pixel); } // Remove the background colour.
}
}
}
fn main() {
for filepath in get_arguments() {
let img = image::open( &Path::new(filepath) ).unwrap();
remove_background( &mut img );
let ref mut fout = File::create(&Path::new("output.png")).unwrap();
img.save(fout, image::PNG);
}
}
It gives the following error:
src/main.rs:32:83: 32:100 error: mismatched types:
expected `<T as image::image::GenericImage>::Pixel`,
found `image::color::Rgba<_>`
(expected associated type,
found struct `image::color::Rgba`) [E0308]
src/main.rs:32 if (dr*dr + dg*dg + db*db).to_uint().unwrap() < 16384 { img.put_pixel(x, y, transparent_pixel); } // Remove the background colour.
This is presumably because the GenericImage struct defines its own internal "Pixel", which I don't think I can access, but is exactly the same as the normal Pixel struct. How would I get code with this functionality to compile? Every other use of put_pixel I've seen has used get_pixel on the image object and manipulated that, but I need to use a transparent pixel, so that won't work.
Chris Morgan is spot on - when you are accepting a GenericImage, you have to handle a generic Pixel. However, you are trying to use a specific one - Rgba. Even more than that, you have to specify the type of the channels of the Rgba.
A notable issue with your original code is: what do you do when the GenericImage is composed of pixels that don't support transparency?
Here's a version that picks some concrete types and compiles:
fn remove_background<T>(img: &mut T)
where T: image::GenericImage<Pixel=image::Rgba<u8>>
{
let background_color = img.get_pixel(0, 0).to_rgba();
if background_color[3].to_uint().unwrap() > 0 {
for (_, _, color) in img.pixels_mut() {
let rgba = color.to_rgba();
let (dr,dg,db) = (rgba[0] - background_color[0],
rgba[1] - background_color[1],
rgba[2] - background_color[2]);
// Remove the background colour.
if (dr*dr + dg*dg + db*db).to_uint().unwrap() < 16384 {
for c in color.channels_mut().iter_mut() { *c = 0 }
}
}
}
}
Beyond specifying the specific pixel type in the where clause, you'll also run into mutability issues. I changed it to pixels_mut, channels_mut, and iter_mut to get the mutability to the right place.
Note that the Rust style is 4-space indents, so I've done that as well.
Related
Is there a way to generate a checkerboard pattern without using nested for loops and without using x and y?
I'm sure this has already been done before, but I couldn't find it in the ~15mins I was looking for it.
Currently I have this function that generates the pattern first extracting x and y:
fn get_bg_color_of(idx: usize) -> &'static str {
const BG_BLACK: &str = "\u{001b}[48;5;126m";
const BG_WHITE: &str = "\u{001b}[48;5;145m";
let x = idx % Board::WIDTH;
let y = idx / Board::WIDTH;
let is_even_row = y % 2 == 0;
let is_even_column = x % 2 == 0;
if is_even_row && is_even_column || !is_even_row && !is_even_column {
return BG_WHITE;
}
BG_BLACK
}
Is there a simpler way to do this? If yes, please also explain how and why, I like to know what's happening in my code :)
If WIDTH is even, then you need to separate x and y. You can write that shorter, though:
fn get_bg_color_of(idx: usize) -> &'static str {
const BG_BLACK: &str = "\u{001b}[48;5;126m";
const BG_WHITE: &str = "\u{001b}[48;5;145m";
if ( (idx + (idx/Board::WIDTH)) % 2 == 0 ) {
return BG_WHITE;
}
return BG_BLACK;
}
Note that this doesn't work if WIDTH is odd. In that case, you can just do:
if ( idx % 2 == 0 ) {
return BG_WHITE;
}
}
If you need to handle both cases, then:
if ( ((idx%Board::WIDTH) + (idx/Board::WIDTH)) % 2 == 0 ) {
return BG_WHITE;
}
I am using a Vec to store a 2D (row major) matrix of values. I would like to iterate over this matrix with a sliding 2D sub-window to apply a filter (which is unfortunately non-separable).
I have seen in the slice documentation that a windows function exists, which is what I want but in 2 dimensions.
I thought about implementing this as:
fn main() {
// 4 rows 3 columns
let dim: (usize, usize) = (4, 3);
// Place-holder matrix
#[rustfmt::skip]
let mat = vec![0, 1, 2,
3, 4, 5,
6, 7, 8,
9, 10, 11];
// 2D index to 1D index
let linearize = |r, c| r * dim.1 + c;
// The dimensions of my sub-window
let win_size: usize = 2;
// Calculate the bounds for which the top left corner of each window may exist
let bounds: (usize, usize) = (dim.0 - win_size + 1, dim.1 - win_size + 1);
// Convert window 1D index into a 2D index
let split = |i| (i / win_size, i % win_size);
// Iterate over all the top left corners
let window_2d = (0..bounds.0 * bounds.1).map(|i| {
// Get the 2D index of the top left corner
let (r, c) = (i / bounds.1, i % bounds.1);
// Borrow the matrix, so our closure may own the reference
let bmat = &mat;
// Return an iterator for this window
return (0..win_size * win_size).map(move |x| {
let (wr, wc) = split(x);
return bmat[linearize(wr + r, wc + c)];
});
});
// Print the windows out
window_2d.for_each(|it| {
print!("[ ");
it.for_each(|x| print!("{} ", x));
println!("]");
});
}
Essentially creating an iterator over a range of indices and then mapping to the square bracket operator of the matrix.
As far as I know, this is going to have the overhead of a bounds check for each deref of the iterator.
I'm wondering if there's an alternative which would elide the bounds checks? Maybe using a combination of chunks, windows and zip, to chunk the matrix into rows, each with a sliding window, then zip the row's windows and flatten the result?
Thanks!
Edit:
I'm not looking to simply iterate over a 2D array, I want to slide a 2D window over the array, similar to how the std::slice::windows function works.
The best I've got for now is wrapping the matrix access in an unsafe block to elide the bounds check.
With some other misc changes, this is the full example now:
fn split_factory(cols: usize) -> impl Fn(usize) -> (usize, usize) {
// Declaring that cols must be positive allows more aggressive optimisation of div and mod.
if cols < 1 {
unreachable!()
}
move |i| (i / cols, i % cols)
}
fn main() {
// 4 rows 3 columns
let dim: (usize, usize) = (4, 3);
// Place-holder matrix
#[rustfmt::skip]
let mat = vec![0, 1, 2,
3, 4, 5,
6, 7, 8,
9, 10, 11];
// The dimensions of my sub-window
let win_dim = (3usize, 2usize);
// Calculate the bounds for which the top left corner of each window may exist
let bounds = (dim.0 - win_dim.0 + 1, dim.1 - win_dim.1 + 1);
// Iterate over all the top left corners
let convolution_iter = (0..bounds.0 * bounds.1)
.map(split_factory(bounds.1))
.map(|(r, c)| {
// Borrow the matrix, so our closure may own the reference
let bmat = &mat;
// Return an iterator for this window
return (0..win_dim.0 * win_dim.1)
.map(split_factory(win_dim.1))
.map(move |(wr, wc)| {
let px = (wr + r) * dim.1 + (wc + c);
(px, unsafe { *bmat.get_unchecked(px) })
});
});
// Print the windows out (badly...)
convolution_iter.for_each(|it| println!("{:?}", it.collect::<Vec<(usize, i32)>>()));
}
Would still be nicer to avoid unsafe and the indirection of looking up the matrix with indices.
JavaScript
for (var x = 0; x < 360; x += 0.5)
{
// ...
}
How do I do this in Kotlin?
Note that my step size is a floating point and so a regular range won't work:
for (x in 0.0 until 360.0 step 0.5) {
// ...
}
I also need to exclude the ending value, hence why I'm using until.
I will resort to a while loop for now:
var x = 0.0;
while (x < 360.0) {
// ...
x += 0.5
}
There isn't a way to do this right now in Kotlin because Kotlin does not have "traditional" for loops. I believe you're right in choosing a while loop. In fact, traditional for loops are just while loops in disguise:
for (init; condition; post;) {
// do something
}
can always be rewritten,
init
while (condition) {
// do something
post
}
with no change in behavior, because the init statement will always execute and the condition will always be checked before the loop runs even once. One thing this construct can't give you is a variable that's only scoped to this block. If you're really after that behavior, the following would work, though it's not very idiomatic.
for (x in generateSequence(0.0) { it + 0.5 }.takeWhile { it < 360.0}) {
println(x)
}
If you're using a Sequence, you might also be interested in the more idiomatic forEach:
generateSequence(0.0) { it + 0.5 }.takeWhile { it < 360.0 }.forEach { x ->
// do something
}
As repeated addition is just a shorthand for multiplication you can look at for (x in 0.0 until 360.0 step 0.5) as "do something for as many times as 0.5 fits in 360". Therefore it would make sense to express it like this:
val times = (360 / 0.5).toInt()
repeat(times){
}
of cause you can also inline times to
repeat(times = (360 / 0.5).toInt()){
}
The advantage is that you skip the sequence generation. Con -- you lose the access to your counting variable x.
see also https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/repeat.html
I agree with Answer by #AdamYakes.
Since the until operator is not available for Floating value type, you can not use
it for floating step value.
However, If you still want to use
for (x in 0.0 until 360.0 step 0.5) {
// use value
}
you can do that as following:
for (x in 0 until 3600 step 5) {
// use (value / 10)
}
Kotlin is so flexible that one could hack a custom solution:
private infix fun (((Double) -> Unit, Double) -> Unit).step(step: Double) =
fun(action: (Double) -> Unit) = this(action, step)
private infix fun Double.upto(to: Double) =
fun(action: (Double) -> Unit, step: Double) {
var v = this
while (v < to) {
action(v)
v += step
}
}
fun main() {
// Usage:
(0.0 upto 360.0 step 0.5) {
println(it)
}
}
What I did above is to create two infix functions.
The upto() infix function can be used with two Doubles: it takes 0.0 upto 360.0 and returns a function that expects two arguments: an action function and the step double value.
The step infix function can be used with functions returned by upto() combined with a Double (so f step 0.5). It returns a function that calls the upto() function passing the step value and the user's { ... } block that gets called for each iteration.
Short and convoluted.
A simpler alternative:
inline fun doubleFor(
from: Double, to: Double, step: Double, action: (Double) -> Unit
) {
var v = from
while (v < to) {
action(v)
v += step
}
}
fun main() {
// Usage:
doubleFor(0.0, 360.0, 0.5) {
println(it)
}
}
A good IDE would show the argument names next to the values making the meaning of the arguments in the usage code obvious.
A third approach can be found at https://stackoverflow.com/a/44332139/2933899 which allows one to write for(x in 0.0 .. 360.0 step 0.5) { println(x) } with the inconvenience that the top boundary value is included.
Run these at https://pl.kotl.in/ZuR354Fas
I have enums that contain variables:
enum Asymmetric {
One(i32),
Two(i32, i32),
}
I want to change just one field of an already existing enum, without reassigning the entire enum. My code (playground):
// Does not compile
fn main() {
let two = Asymmetric::Two(4, 5);
let mut vec = vec![two];
foo(&mut vec[0]);
}
fn foo(baa: &mut Asymmetric) {
match baa {
&mut Asymmetric::Two(x0, x1) => {
x0 = 6;
}
_ => {}
}
}
This results in this error:
error[E0384]: re-assignment of immutable variable `x0`
--> src/main.rs:16:13
|
15 | &mut Asymmetric::Two(x0, x1) => {
| -- first assignment to `x0`
16 | x0 = 6;
| ^^^^^^ re-assignment of immutable variable
Thanks to "match ergonomics" (introduced in Rust 1.26, proposed here), you can write your code like this:
fn foo(baa: &mut Asymmetric) {
match baa {
Asymmetric::Two(x0, _) => {
*x0 = 6;
}
_ => {}
}
}
Since baa is a mutable reference, but your pattern you're matching against (Asymmetric::Two(x0, _)) is not, the name x0 is automatically bound as mutable reference.
You can also do it manually by using ref mut. See this working code (playground):
fn foo(baa: &mut Asymmetric) {
match *baa {
Asymmetric::Two(ref mut x0, _) => {
*x0 = 6;
}
_ => {}
}
}
Some minor changes that are not related to your error, but which increase your code quality:
usually you deref (with *) the matched-on value instead of adding & or &mut to every pattern in the match
you should use _ as a name placeholder if you don't need to bind to that name
In your case, you can simplify the code even further by using if let. Whenever you are only interested in one match-case, you should use if let instead:
fn foo(baa: &mut Asymmetric) {
if let Asymmetric::Two(x0, _) = baa {
*x0 = 6;
}
}
I have been looking at examples of FFTs in Swift, and they all seem to have ConstUnsafePointer when using vDSP_ctozD as in the example below:
import Foundation
import Accelerate
internal func spectrumForValues(signal: [Double]) -> [Double] {
// Find the largest power of two in our samples
let log2N = vDSP_Length(log2(Double(signal.count)))
let n = 1 << log2N
let fftLength = n / 2
// This is expensive; factor it out if you need to call this function a lot
let fftsetup = vDSP_create_fftsetupD(log2N, FFTRadix(kFFTRadix2))
var fft = [Double](count:Int(n), repeatedValue:0.0)
// Generate a split complex vector from the real data
var realp = [Double](count:Int(fftLength), repeatedValue:0.0)
var imagp = realp
withExtendedLifetimes(realp, imagp) {
var splitComplex = DSPDoubleSplitComplex(realp:&realp, imagp:&imagp)
// Take the fft
vDSP_fft_zripD(fftsetup, &splitComplex, 1, log2N, FFTDirection(kFFTDirection_Forward))
// Normalize
var normFactor = 1.0 / Double(2 * n)
vDSP_vsmulD(splitComplex.realp, 1, &normFactor, splitComplex.realp, 1, fftLength)
vDSP_vsmulD(splitComplex.imagp, 1, &normFactor, splitComplex.imagp, 1, fftLength)
// Zero out Nyquist
splitComplex.imagp[0] = 0.0
// Convert complex FFT to magnitude
vDSP_zvmagsD(&splitComplex, 1, &fft, 1, fftLength)
}
// Cleanup
vDSP_destroy_fftsetupD(fftsetup)
return fft
}
// To get rid of the `() -> () in` casting
func withExtendedLifetime<T>(x: T, f: () -> ()) {
return Swift.withExtendedLifetime(x, f)
}
// In the spirit of withUnsafePointers
func withExtendedLifetimes<A0, A1>(arg0: A0, arg1: A1, f: () -> ()) {
return withExtendedLifetime(arg0) { withExtendedLifetime(arg1, f) }
}
However when I try to use it in my project, this ConstUnsafePointer is seen as an unresolved identifier. Any clue how to fix this? Thanks in advance.
The name ConstUnsafePointer was used in early Swift betas last summer (at that time, UnsafePointer meant mutable). Now, constant pointers are just UnsafePointer and mutable pointers are UnsafeMutablePointer.