Skip to content

Commit d7051fd

Browse files
committed
Fixed open issues
1 parent 286a477 commit d7051fd

File tree

4 files changed

+211
-110
lines changed

4 files changed

+211
-110
lines changed

.github/workflows/rust.yml

Lines changed: 86 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,101 @@
1-
name: Rust
1+
name: Rust test
22

33
on:
44
push:
55
branches: [ main ]
66
pull_request:
77
branches: [ main ]
88

9-
env:
10-
CARGO_TERM_COLOR: always
9+
permissions:
10+
contents: read
1111

1212
jobs:
1313
build:
1414
strategy:
1515
matrix:
16-
os: [ ubuntu-latest ]
17-
rust: [ stable, nightly ]
16+
os: [ubuntu-latest]
17+
linkage:
18+
- dynamic
19+
rust: [stable]
1820
runs-on: ${{ matrix.os }}
1921

2022
steps:
21-
- name: Download deps
22-
run: sudo apt update && sudo apt install -y clang libclang-dev libopencv-dev
23-
- uses: actions/checkout@v3
24-
- name: Build
25-
run: cargo build --verbose
26-
- name: Run tests
27-
run: cargo test --verbose
23+
- name: Checkout repository
24+
uses: actions/checkout@v4
25+
26+
- name: Setup Rust
27+
uses: dtolnay/rust-toolchain@stable
28+
with:
29+
toolchain: ${{ matrix.rust }}
30+
components: clippy
31+
32+
- name: Install OpenCV build dependencies
33+
run: |
34+
sudo apt-get update
35+
sudo apt-get install -y \
36+
build-essential cmake git pkg-config \
37+
libgtk-3-dev \
38+
libavcodec-dev libavformat-dev libswscale-dev \
39+
libtbb-dev \
40+
clang libclang-dev
41+
42+
# Clone OpenCV repositories before checking cache
43+
- name: Clone OpenCV repositories
44+
run: |
45+
OPENCV_VERSION=4.11.0
46+
git clone --depth 1 --branch $OPENCV_VERSION https://github.com/opencv/opencv.git
47+
git clone --depth 1 --branch $OPENCV_VERSION https://github.com/opencv/opencv_contrib.git
48+
mkdir -p opencv/build
49+
50+
# Cache OpenCV build
51+
- name: Cache OpenCV build
52+
id: opencv-cache
53+
uses: actions/cache@v3
54+
with:
55+
path: |
56+
opencv/build
57+
/usr/local/include/opencv4
58+
/usr/local/lib/libopencv_*
59+
/usr/local/lib/pkgconfig/opencv*
60+
key: opencv-${{ runner.os }}-${{ hashFiles('opencv/CMakeLists.txt') }}-4.11.0
61+
62+
# Only build OpenCV if cache miss
63+
- name: Build OpenCV from source
64+
if: steps.opencv-cache.outputs.cache-hit != 'true'
65+
run: |
66+
cd opencv/build
67+
cmake \
68+
-DCMAKE_BUILD_TYPE=RELEASE \
69+
-DCMAKE_INSTALL_PREFIX=/usr/local \
70+
-DOPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules \
71+
-DBUILD_opencv_world=ON \
72+
-DBUILD_TESTS=OFF \
73+
-DBUILD_EXAMPLES=OFF ..
74+
make -j$(nproc)
75+
sudo make install
76+
sudo ldconfig
77+
78+
# Install from cache if cache hit
79+
- name: Install OpenCV from cache
80+
if: steps.opencv-cache.outputs.cache-hit == 'true'
81+
run: |
82+
sudo cp -r /usr/local/include/opencv4 /usr/local/include/ || true
83+
sudo cp -r /usr/local/lib/libopencv_* /usr/local/lib/ || true
84+
sudo cp -r /usr/local/lib/pkgconfig/opencv* /usr/local/lib/pkgconfig/ || true
85+
sudo ldconfig
86+
87+
- name: Set OpenCV env vars (required by opencv crate)
88+
run: |
89+
echo "PKG_CONFIG_PATH=/usr/local/lib/pkgconfig" >> $GITHUB_ENV
90+
echo "OPENCV_INCLUDE_PATHS=/usr/local/include/opencv4" >> $GITHUB_ENV
91+
echo "OPENCV_LINK_LIBS=opencv_world" >> $GITHUB_ENV
92+
echo "OPENCV_LINK_PATHS=/usr/local/lib" >> $GITHUB_ENV
93+
94+
- name: Clippy
95+
run: cargo clippy --all --all-targets --features "clang-runtime"
96+
97+
- name: Build
98+
run: cargo build --verbose --all --all-targets --features "clang-runtime"
99+
100+
- name: Run tests
101+
run: cargo test --verbose --features "clang-runtime"

README.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Read more about image alignment with OpenCV [here](https://learnopencv.com/image
2020
Opencv-rust can be little tricky to install. Follow the instructions from [rust opencv](https://crates.io/crates/opencv)
2121

2222
You will need the "clang-runtime" feature if you <a href="https://github.com/twistedfall/opencv-rust#Troubleshooting">experience problems with your clang environment</a>
23-
.
23+
Disclaimer: the library is only built and tested against opencv 4.11.0.
2424

2525
```bash
2626
cargo build --release
@@ -50,8 +50,8 @@ The result should be two windows showing the stacked images using two different
5050
## API
5151
```rust
5252
let keypoint_match_img:opencv::core::Mat = keypoint_match(
53-
// a Vec<PathBuf> containing paths to image files
54-
collect_image_files(&PathBuf::from("image_stacking_py/images"))?,
53+
// any IntoIter containing paths to image files
54+
vec!["1.jpg","2.jpg","3.jpg","4.jpg","5.jpg"],
5555
KeyPointMatchParameters {
5656
method: opencv::calib3d::RANSAC,
5757
ransac_reproj_threshold: 5.0,
@@ -62,8 +62,8 @@ let keypoint_match_img:opencv::core::Mat = keypoint_match(
6262
Depending on the parameters the `ecc_match()` is much slower, but also more accurate.
6363
```rust
6464
let ecc_match_img:opencv::core::Mat = ecc_match(
65-
// a Vec<PathBuf> containing paths to image files
66-
collect_image_files(&PathBuf::from("image_stacking_py/images"))?,
65+
// any IntoIter containing paths to image files
66+
vec!["1.jpg","2.jpg","3.jpg","4.jpg","5.jpg"],
6767
EccMatchParameters {
6868
motion_type: MotionType::Homography,
6969
max_count: Some(5000),
@@ -75,11 +75,11 @@ let ecc_match_img:opencv::core::Mat = ecc_match(
7575

7676
## Todo
7777

78-
* Figure out the docs.rs problem
79-
* Figure out what to do with `.reshape()` in `keypoint_match()`
78+
* ~~Figure out what to do with `.reshape()` in `keypoint_match()`~~ fixed?
8079
* ~~Figure out some opencv parameters~~ responsibility sneakily shifted to end user.
81-
* Complete the `sharpness_tenengrad()` function. Mat not square?
82-
* Command line options in the example
80+
* ~~Complete the `sharpness_tenengrad()` function. Mat not square?~~
81+
* (optionally) Reduce resolution before doing orb/ecc matching,
82+
* options in the example
8383

8484
## License
8585

examples/main.rs

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,52 +2,74 @@
22
// Copyright (c) 2021,2025 lacklustr@protonmail.com https://github.com/eadf
33

44
use libstacker::opencv::{highgui, imgcodecs};
5+
use libstacker::prelude::*;
56
use rayon::prelude::*;
67
use std::path;
78

9+
/// Returns paths to all jpg,jpeg,tif and png files in a single directory (non-recursive)
10+
pub fn collect_image_files(
11+
path: &std::path::Path,
12+
) -> Result<Vec<std::path::PathBuf>, StackerError> {
13+
Ok(std::fs::read_dir(path)?
14+
.flatten()
15+
.filter_map(|f| f.path().is_file().then(|| f.path()))
16+
.filter(|p| p.extension().is_some() && p.extension().unwrap().to_str().is_some())
17+
.filter(|p| {
18+
let extension = p.extension().unwrap().to_str().unwrap().to_uppercase();
19+
extension == "JPG"
20+
|| extension == "JPEG"
21+
|| extension == "TIF"
22+
|| extension == "PNG"
23+
})
24+
.collect())
25+
}
26+
827
/// Run an example aligning images found under "image_stacking_py/images"
928
/// The example displays two images, one is aligned with the `keypoint_match()` method,
1029
/// the other with `ecc_match()`
11-
fn main() -> Result<(), libstacker::StackerError> {
30+
fn main() -> Result<(), StackerError> {
1231
use libstacker::opencv::core::Point;
1332

1433
let v = vec![Point::new(1, 5), Point::new(2, 5), Point::new(3, 5)];
1534
let _ = v
1635
.into_iter()
1736
.collect::<libstacker::opencv::core::Vector<Point>>();
1837

19-
let files = libstacker::collect_image_files(&path::PathBuf::from("image_stacking_py/images"))?;
38+
let files = collect_image_files(&path::PathBuf::from("image_stacking_py/images"))?;
2039
let now = std::time::Instant::now();
2140
let mut files = files
2241
.into_par_iter()
23-
.map(move |f| -> Result<_, libstacker::StackerError> {
42+
.map(move |f| -> Result<_, StackerError> {
2443
let img_gray = imgcodecs::imread(f.to_str().unwrap(), imgcodecs::IMREAD_GRAYSCALE)?;
2544
Ok((
2645
f,
27-
libstacker::sharpness_modified_laplacian(&img_gray)?,
28-
libstacker::sharpness_variance_of_laplacian(&img_gray)?,
29-
libstacker::sharpness_tenengrad(&img_gray, 3)?,
30-
libstacker::sharpness_normalized_gray_level_variance(&img_gray)?,
46+
libstacker::sharpness_modified_laplacian(&img_gray)?, // LAPM = 1
47+
libstacker::sharpness_variance_of_laplacian(&img_gray)?, // LAPV = 2
48+
libstacker::sharpness_tenengrad(&img_gray, 3)?, // TENG = 3
49+
libstacker::sharpness_normalized_gray_level_variance(&img_gray)?,// GLVN = 4
3150
))
3251
})
33-
.collect::<Result<Vec<_>, libstacker::StackerError>>()?;
52+
.collect::<Result<Vec<_>, StackerError>>()?;
3453
println!("Calculated sharpness() in {:?}", now.elapsed());
3554

36-
// sort images by sharpness using LAPM for now
37-
files.sort_by_key(|f| ordered_float::OrderedFloat(f.1));
55+
// sort images by sharpness using TENG for now
56+
files.sort_by_key(|f| ordered_float::OrderedFloat(f.3));
3857

58+
println!("Files ordered by TENG (low quality first)");
3959
for f in files.iter() {
4060
println!(
4161
"{:?} LAPM:{: >8.5} LAPV:{: >9.5} TENG:{: >8.5} GLVN:{: >9.5}",
4262
f.0, f.1, f.2, f.3, f.4
4363
);
4464
}
45-
// only keep the filename and skip the last file (the bad one)
46-
let files: Vec<_> = files.into_iter().map(|f| f.0).rev().skip(1).rev().collect();
65+
// only keep the filename and skip the first file (the bad one) and reverse the order
66+
// keeping the best image first.
67+
let files: Vec<_> = files.into_iter().map(|f| f.0).skip(1).rev().collect();
68+
//println!("Using these files {:?}", files);
4769

4870
let now = std::time::Instant::now();
49-
let keypoint_match_img = libstacker::keypoint_match(
50-
files.clone(),
71+
let keypoint_match_img = keypoint_match(
72+
&files,
5173
libstacker::KeyPointMatchParameters {
5274
method: opencv::calib3d::RANSAC,
5375
ransac_reproj_threshold: 5.0,
@@ -68,8 +90,8 @@ fn main() -> Result<(), libstacker::StackerError> {
6890
println!("Calculated ecc_match() in {:?}", now.elapsed());
6991

7092
while highgui::wait_key(33)? != 27 {
71-
let _ = highgui::imshow("KeyPoint match", &keypoint_match_img)?;
72-
let _ = highgui::imshow("ECC match", &ecc_match_img)?;
93+
highgui::imshow("KeyPoint match", &keypoint_match_img)?;
94+
highgui::imshow("ECC match", &ecc_match_img)?;
7395
}
7496
Ok(())
75-
}
97+
}

0 commit comments

Comments
 (0)