image-rs / image

Encoding and decoding images in Rust
Apache License 2.0
5.01k stars 619 forks source link

Cropping a rotated rectangle #1770

Closed gbaranski closed 8 months ago

gbaranski commented 2 years ago

Hi, how do I crop a rotated rectangle?

I know I can use min_area_rect from imageproc::geometry, and then rotate the image, but is there some example on how to do that? I'm not too good at math and geometry stuff.

Thanks

jgoday commented 2 years ago

Hi @gbaranski , I'm not sure I fully understand the problem,

but given at least two image points, you find the minimum area that covers all of them, crop the image and then rotates it.

If you want to use geometric_transformations::rotate, (assuming that you want to rotate the new croped image from his center), you must specify the center of the new image (width/2, height/2).

use image::io::Reader as ImageReader;
use image::{ImageResult, Rgb};
use imageproc::geometric_transformations::{rotate, Interpolation};
use imageproc::geometry::min_area_rect;
use imageproc::point::Point;
use std::f32::consts::PI;

fn main() -> ImageResult<()> {
    let mut img = ImageReader::open("myimage.png")?.decode()?;

    let points = vec![Point { x: 100, y: 100 }, Point { x: 300, y: 420 }];
    let rect = min_area_rect(&points);

    let [tl, tr, br, _] = rect;

    let width = tr.x - tl.x;
    let height = br.y - tl.y;

    //    let img = img.crop(tl.x, tl.y, width, height).rotate90();
    let angle_in_radians = 90.0 * PI / 180.0;
    let img = img.crop(tl.x, tl.y, width, height).to_rgb16();
    let img = rotate(
        &img,
        (width as f32 / 2.0, height as f32 / 2.0),
        angle_in_radians,
        Interpolation::Bilinear,
        Rgb([0, 0, 0]),
    );

    img.save("test.png")
}