Compare commits

..

8 Commits
master ... qt

Author SHA1 Message Date
Andrey Tkachenko
eefc851af5 Additional Pixels 2014-07-23 15:44:35 +04:00
Andrey Tkachenko
5ab294bfa8 QtV2 2014-07-22 20:37:29 +04:00
Andrey Tkachenko
16cd697457 Add some images 2014-07-18 20:49:26 +04:00
Andrey Tkachenko
60ff52a6e4 V2 begin 2014-07-18 20:48:42 +04:00
Andrey Tkachenko
cae9dc0641 Update image 2014-07-14 18:05:08 +04:00
Andrey Tkachenko
ef41b0c59a Qt fix 2014-07-14 10:55:56 +04:00
Andrey Tkachenko
772bf4e9ae Migrate to Qt 2014-07-11 20:35:48 +04:00
Andrey Tkachenko
c7be57824a Latest 2014-07-11 20:32:56 +04:00
40 changed files with 1142 additions and 529 deletions

View File

@ -1,14 +0,0 @@
kind: pipeline
name: default
steps:
- name: build
image: rust
commands:
- cargo build --verbose --all
- name: fmt-check
image: rust
commands:
- rustup component add rustfmt
- cargo fmt --all -- --check

4
.gitignore vendored
View File

@ -1,3 +1 @@
/target
.undodir
CSV.pro.user

46
CSV.pro Normal file
View File

@ -0,0 +1,46 @@
#-------------------------------------------------
#
# Project created by QtCreator 2014-07-10T12:35:18
#
#-------------------------------------------------
QT += core gui qml quick widgets
TEMPLATE = app
TARGET = CSV
CONFIG += c++11
CONFIG += j4
CONFIG -= console
SOURCES += main.cpp \
svimage.cpp \
svworker.cpp \
svprocessor.cpp \
svkernelv1.cpp \
svkernelv2.cpp \
svimageprovider.cpp \
svpoint.cpp \
svcurve.cpp \
svsimplepoint.cpp \
svfigure.cpp \
svobject.cpp
HEADERS += \
svimage.h \
svworker.h \
svprocessor.h \
svabstractkernel.h \
svkernelv1.h \
svkernelv2.h \
svimageprovider.h \
svpoint.h \
svcurve.h \
svsimplepoint.h \
svfigure.h \
svobject.h
RESOURCES += \
resource.qrc
OTHER_FILES += \
Main.qml

339
Cargo.lock generated
View File

@ -1,339 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "adler32"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
[[package]]
name = "anyhow"
version = "1.0.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203"
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bytemuck"
version = "1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72957246c41db82b8ef88a5486143830adeb8227ef9837740bdec67724cf2c5b"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "color_quant"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "crc32fast"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3825b1e8580894917dc4468cb634a1b4e9745fddc854edad72d9c04644c0319f"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
dependencies = [
"cfg-if",
"crossbeam-utils",
"lazy_static",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
dependencies = [
"cfg-if",
"lazy_static",
]
[[package]]
name = "deflate"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174"
dependencies = [
"adler32",
"byteorder",
]
[[package]]
name = "dispmap"
version = "0.1.0"
dependencies = [
"anyhow",
"image",
"rayon",
]
[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "gif"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3a7187e78088aead22ceedeee99779455b23fc231fe13ec443f99bb71694e5b"
dependencies = [
"color_quant",
"weezl",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "image"
version = "0.23.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1"
dependencies = [
"bytemuck",
"byteorder",
"color_quant",
"gif",
"jpeg-decoder",
"num-iter",
"num-rational",
"num-traits",
"png",
"scoped_threadpool",
"tiff",
]
[[package]]
name = "jpeg-decoder"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2"
dependencies = [
"rayon",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.108"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119"
[[package]]
name = "memoffset"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
dependencies = [
"autocfg",
]
[[package]]
name = "miniz_oxide"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
dependencies = [
"adler32",
]
[[package]]
name = "miniz_oxide"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
dependencies = [
"adler",
"autocfg",
]
[[package]]
name = "num-integer"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "png"
version = "0.16.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
dependencies = [
"bitflags",
"crc32fast",
"deflate",
"miniz_oxide 0.3.7",
]
[[package]]
name = "rayon"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
dependencies = [
"autocfg",
"crossbeam-deque",
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"lazy_static",
"num_cpus",
]
[[package]]
name = "scoped_threadpool"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "tiff"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437"
dependencies = [
"jpeg-decoder",
"miniz_oxide 0.4.4",
"weezl",
]
[[package]]
name = "weezl"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b77fdfd5a253be4ab714e4ffa3c49caf146b4de743e97510c0656cf90f1e8e"

View File

@ -1,16 +0,0 @@
[package]
name = "dispmap"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[[bin]]
name = "run"
path = "./bin/run.rs"
[dependencies]
anyhow = "1.0.51"
image = "0.23.14"
rayon = "1.5.1"

225
Main.qml Normal file
View File

@ -0,0 +1,225 @@
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.1
ApplicationWindow {
id: mainWindow
visible: true
width: 800
height: 600
statusBar: StatusBar {
Row {
Label {
id: statusBarState
text: "In Progress"
}
}
}
Connections {
target: processor
onFinished: {
statusBarState.text = "Ready " + elapsedTime;
}
}
Item {
anchors.fill: parent
Item {
id: leftColumn
width: 200
anchors.bottom: parent.bottom
anchors.top: parent.top
anchors.right: rightColumn.left
anchors.left: parent.left
Component {
id: slider
Item {
property alias title: sliderTitle.text
property alias from: sliderSlider.minimumValue
property alias to: sliderSlider.maximumValue
property alias step: sliderSlider.stepSize
property string name: ''
height: 50
Text {
id: sliderTitle
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.leftMargin: 15
anchors.rightMargin: 10
anchors.topMargin: 10
text: ""
}
Text {
id: sliderValue
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: sliderSlider.top
text: sliderSlider.value
}
Slider {
id: sliderSlider
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.leftMargin: 10
anchors.rightMargin: 10
stepSize: 1
}
}
}
Column {
anchors.bottom: renderButton.top
anchors.top: parent.top
anchors.right: parent.right
anchors.left: parent.left
Loader {
id: windowSize
sourceComponent: slider
anchors.left: parent.left
anchors.right: parent.right
onLoaded: {
windowSize.item.title = "Window Size"
windowSize.item.from = 0;
windowSize.item.to = 10;
windowSize.item.step = 1;
}
}
Loader {
id: matchSize
sourceComponent: slider
anchors.left: parent.left
anchors.right: parent.right
onLoaded: {
matchSize.item.title = "Match Size"
matchSize.item.from = 0;
matchSize.item.to = 10;
matchSize.item.step = 1;
}
}
Loader {
id: errorLevel
sourceComponent: slider
anchors.left: parent.left
anchors.right: parent.right
onLoaded: {
errorLevel.item.title = "Error Level"
errorLevel.item.from = 0;
errorLevel.item.to = 10;
errorLevel.item.step = 1;
}
}
}
Button {
id: renderButton
//anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
Text {
anchors.centerIn: parent
text: "Render"
}
}
}
Item {
id: rightColumn
anchors.bottom: parent.bottom
anchors.top: parent.top
anchors.right: parent.right
anchors.left: leftColumn.right
TabView {
anchors.fill: parent
Tab {
id: imageView
title: "Image View"
Item {
Flickable {
anchors.fill: parent
contentWidth: image.width
contentHeight: image.height
interactive: true
anchors.margins: 2
clip: true
Item {
Image {
id: image
source: ""
smooth: false
}
Connections {
target: processor
onFinished: {
image.source = "image://images/result";
}
}
}
}
}
}
Tab {
id: leftImageView
title: "Left Image"
Item {
Flickable {
anchors.fill: parent
contentWidth: image.width
contentHeight: image.height
interactive: true
anchors.margins: 2
clip: true
Item {
Image {
id: leftImage
source: "image://images/left"
smooth: false
}
}
}
}
}
Tab {
id: rightImageView
title: "Right Image"
Item {
Flickable {
anchors.fill: parent
contentWidth: image.width
contentHeight: image.height
interactive: true
anchors.margins: 2
clip: true
Item {
Image {
id: rightImage
source: "image://images/right"
smooth: false
}
}
}
}
}
}
}
}
}

View File

@ -1,3 +0,0 @@
# Simple Disparity Map Algorithm
![example](disp.png "Example")

View File

@ -1,20 +0,0 @@
use dispmap::compute;
fn main() -> anyhow::Result<()> {
let mut args = std::env::args();
let _ = args.next();
let left_path = args.next().unwrap();
let right_path = args.next().unwrap();
println!("disparity for {} {}", left_path, right_path);
let left = image::open(left_path)?.to_rgb8();
let right = image::open(right_path)?.to_rgb8();
let disp = compute(&left, &right);
disp.save("disp.png")?;
Ok(())
}

14
cl/kernel.cl Normal file
View File

@ -0,0 +1,14 @@
__kernel void ProcessLine(__global const float* a, __global const float* b, __global float* c, int iNumElements)
{
// get index into global data array
int iGID = get_global_id(0);
// bound check (equivalent to the limit on a 'for' loop for standard/serial C code
if (iGID >= iNumElements)
{
return;
}
// add the vector elements
c[iGID] = a[iGID] + b[iGID];
}

BIN
disp.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

BIN
img/left1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 MiB

After

Width:  |  Height:  |  Size: 2.1 MiB

BIN
img/right1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 MiB

After

Width:  |  Height:  |  Size: 2.1 MiB

39
main.cpp Normal file
View File

@ -0,0 +1,39 @@
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlComponent>
#include <QQmlContext>
#include <QPixmap>
#include "svimage.h"
#include "svprocessor.h"
#include "svimageprovider.h"
int main(int argc, char *argv[])
{
QGuiApplication a(argc, argv);
QQmlApplicationEngine engine;
SvImageProvider imageProvider;
QImage imgLeft("../CSV/img/left1.png");
QImage imgRight("../CSV/img/right1.png");
QImage imgStereo(imgLeft.width(), imgLeft.height(), QImage::Format_RGB32);
SvImage left(imgLeft);
SvImage right(imgRight);
SvImage stereo(imgStereo);
SvProcessor proc(&left, &right, &stereo, 4, 2);
imageProvider.addImage("left", &left);
imageProvider.addImage("right", &right);
imageProvider.addImage("result", &stereo);
engine.addImageProvider("images", &imageProvider);
engine.load(QUrl(QStringLiteral("qrc:///Main.qml")));
engine.rootContext()->setContextProperty("processor", &proc);
proc.start();
return a.exec();
}

7
resource.qrc Normal file
View File

@ -0,0 +1,7 @@
<RCC>
<qresource prefix="/">
<file>Main.qml</file>
<file>img/left4.png</file>
<file>img/right4.png</file>
</qresource>
</RCC>

View File

@ -1,134 +0,0 @@
use image::{buffer::PixelsMut, GenericImageView, GrayImage, Luma, Rgb, RgbImage};
fn diff(left: Rgb<u8>, right: Rgb<u8>) -> i32 {
let r = (left[0] as i32 - right[0] as i32).abs();
let g = (left[1] as i32 - right[1] as i32).abs();
let b = (left[2] as i32 - right[2] as i32).abs();
let color = (g - r).abs() + (b - g).abs();
(r + g + b) + color * 4
}
fn match_box(left: [Rgb<u8>; 16], right: [Rgb<u8>; 16]) -> i32 {
let mut sqr_sum = 0;
for (l, r) in left.into_iter().zip(right.into_iter()) {
sqr_sum += diff(l, r);
}
sqr_sum
}
fn px(img: &RgbImage, x: u32, y: u32) -> Rgb<u8> {
if x >= img.width() || y >= img.height() {
return Rgb([0, 0, 0]);
}
img.get_pixel(x, y).clone()
}
fn match_pixels(left: &RgbImage, right: &RgbImage, x: u32, y: u32, j: u32) -> i32 {
let lx = x;
let rx = x + j;
match_box(
[
px(left, lx, y),
px(left, lx + 1, y),
px(left, lx + 2, y),
px(left, lx + 3, y),
px(left, lx, y + 1),
px(left, lx + 1, y + 1),
px(left, lx + 2, y + 1),
px(left, lx + 3, y + 1),
px(left, lx, y + 2),
px(left, lx + 1, y + 2),
px(left, lx + 2, y + 2),
px(left, lx + 3, y + 2),
px(left, lx, y + 3),
px(left, lx + 1, y + 3),
px(left, lx + 2, y + 3),
px(left, lx + 3, y + 3),
],
[
px(right, rx, y),
px(right, rx + 1, y),
px(right, rx + 2, y),
px(right, rx + 3, y),
px(right, rx, y + 1),
px(right, rx + 1, y + 1),
px(right, rx + 2, y + 1),
px(right, rx + 3, y + 1),
px(right, rx, y + 2),
px(right, rx + 1, y + 2),
px(right, rx + 2, y + 2),
px(right, rx + 3, y + 2),
px(right, rx, y + 3),
px(right, rx + 1, y + 3),
px(right, rx + 2, y + 3),
px(right, rx + 3, y + 3),
],
)
}
fn get_pixel_color(image: &RgbImage, cursor: i32) -> f32 {
if cursor == 0 {
return 0.0;
}
(10 * image.width()) as f32 / (2.0 * 0.9 * cursor as f32)
}
fn get_pixel_hue(image: &RgbImage, x: u32, y: u32) -> i32 {
let pixel = image.get_pixel(x, y);
(pixel[1] as i32 - pixel[0] as i32).abs() + (pixel[2] as i32 - pixel[1] as i32).abs()
}
fn exec<'a>(res: PixelsMut<'a, Luma<u8>>, left: &RgbImage, right: &RgbImage, line: u32) {
let mut cursor = 0i32;
let window_size = 128u32;
for (x, res) in res.enumerate() {
let mut closest = -1i32;
let mut min_error = -1i32;
let mut matched = 0;
let _val = get_pixel_hue(left, x as _, line);
for i in 1..window_size {
let _dist = (cursor - i as i32).abs();
let tmp = match_pixels(left, right, x as _, line as _, i as _);
let tmp_smoothed = tmp; // + (dist) * (1.0 / diff);
if tmp_smoothed < min_error || min_error == -1 {
min_error = tmp_smoothed;
closest = i as i32;
matched = 1;
} else if tmp_smoothed == min_error
&& ((cursor - i as i32).abs() < (cursor - closest).abs())
{
closest = i as i32;
matched += 1;
}
}
if matched == 1 {
cursor = closest;
}
*res = Luma([get_pixel_color(left, cursor) as u8]);
}
}
pub fn compute(left: &RgbImage, right: &RgbImage) -> GrayImage {
let mut out = GrayImage::new(left.width(), right.height());
out.rows_mut()
.enumerate()
.for_each(|(y, row)| exec(row, left, right, y as _));
out
}

22
svabstractkernel.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef SVABSTRACTKERNEL_H
#define SVABSTRACTKERNEL_H
#include "svimage.h"
class SvAbstractKernel
{
protected:
SvImage* m_left;
SvImage* m_right;
SvImage* m_result;
public:
void setLeftImage(SvImage* image) {m_left = image;}
void setRightImage(SvImage* image) {m_right = image;}
void setResultImage(SvImage* image) {m_result = image;}
virtual void exec(int line) = 0;
virtual ~SvAbstractKernel() {}
};
#endif // SVABSTRACTKERNEL_H

5
svcurve.cpp Normal file
View File

@ -0,0 +1,5 @@
#include "svcurve.h"
SvCurve::SvCurve()
{
}

19
svcurve.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef SVCURVE_H
#define SVCURVE_H
#include "svpoint.h"
class SvPoint;
class SvCurve
{
protected:
SvPoint *m_ends;
SvPoint *m_points;
SvSimplePoint *m_keyPoints;
public:
SvCurve();
};
#endif // SVCURVE_H

5
svfigure.cpp Normal file
View File

@ -0,0 +1,5 @@
#include "svfigure.h"
SvFigure::SvFigure()
{
}

17
svfigure.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef SVFIGURE_H
#define SVFIGURE_H
#include "svpoint.h"
#include "svcurve.h"
class SvFigure
{
protected:
SvPoint ends[2];
public:
SvFigure();
};
#endif // SVFIGURE_H

148
svimage.cpp Normal file
View File

@ -0,0 +1,148 @@
#include "svimage.h"
int SvImage::getPixel(int x, int y, int channel) {
if (y >= m_image->height() ||
y < 0 ||
x >= m_image->width()
|| x < 0) {
return 0;
}
QRgb rgb = m_image->pixel(x, y);
switch (channel) {
case 0:
return qRed(rgb);
case 1:
return qGreen(rgb);
case 2:
return qBlue(rgb);
default:
return qGray(rgb);
}
}
int SvImage::getPixelNormalizedHue(int x, int y) {
if (y >= m_image->height() ||
y < 0 ||
x >= m_image->width()
|| x < 0) {
return 0;
}
QRgb rgb = m_image->pixel(x, y);
QColor color(rgb);
return (color.hsvHue() * getPixelSaturation(x, y)) / 255;
}
int SvImage::getPixelHue(int x, int y) {
if (y >= m_image->height() ||
y < 0 ||
x >= m_image->width()
|| x < 0) {
return 0;
}
QRgb rgb = m_image->pixel(x, y);
QColor color(rgb);
return color.hsvHue();
}
int SvImage::getPixelValue(int x, int y) {
if (y >= m_image->height() ||
y < 0 ||
x >= m_image->width()
|| x < 0) {
return 0;
}
QRgb rgb = m_image->pixel(x, y);
QColor color(rgb);
return color.value();
}
int SvImage::getPixelSaturation(int x, int y)
{
if (y >= m_image->height() ||
y < 0 ||
x >= m_image->width()
|| x < 0) {
return 0;
}
QRgb rgb = m_image->pixel(x, y);
QColor color(rgb);
return color.saturation();
}
QRgb SvImage::getPixelRGB(int x, int y)
{
if (y >= m_image->height() ||
y < 0 ||
x >= m_image->width()
|| x < 0) {
return 0;
}
return m_image->pixel(x, y);
}
void SvImage::putGrayPixel(int x, int y, int value)
{
if (y >= m_image->height() ||
y < 0 ||
x >= m_image->width()
|| x < 0) {
return;
}
if (value > 255) {
value = 255;
}
m_image->setPixel(x, y, qRgb(value, value, value));
}
void SvImage::putPixel(int x, int y, int red, int green, int blue)
{
if (y >= m_image->height() ||
y < 0 ||
x >= m_image->width()
|| x < 0) {
return;
}
m_image->setPixel(x, y, qRgb(red, green, blue));
}
unsigned int SvImage::getHeight() {
return m_image->height();
}
unsigned int SvImage::getWidth() {
return m_image->width();
}
QImage& SvImage::getImage() {
return *m_image;
}
SvImage::SvImage(QImage& image) {
m_image = &image;
}
SvImage::~SvImage() {
}

32
svimage.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef SVIMAGE_H
#define SVIMAGE_H
#include <QImage>
#include <QRgb>
#include <QColor>
class SvImage
{
protected:
QImage* m_image;
public:
int getPixel(int x, int y, int channel = -1);
int getPixelHue(int x, int y);
int getPixelNormalizedHue(int x, int y);
int getPixelValue(int x, int y);
int getPixelSaturation(int x, int y);
QRgb getPixelRGB(int x, int y);
void putGrayPixel(int x, int y, int val);
void putPixel(int x, int y, int red, int green, int blue);
unsigned int getHeight();
unsigned int getWidth();
QImage& getImage();
SvImage(QImage& image);
virtual ~SvImage();
};
#endif // SVIMAGE_H

27
svimageprovider.cpp Normal file
View File

@ -0,0 +1,27 @@
#include "svimageprovider.h"
SvImageProvider::SvImageProvider():
QQuickImageProvider(QQuickImageProvider::Image)
{
}
QImage SvImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
Q_UNUSED(requestedSize)
SvImage* image = m_images[id];
if (image) {
*size = QSize(image->getWidth(), image->getHeight());
return image->getImage();
}
return QImage(0, 0, QImage::Format_RGB32);
}
void SvImageProvider::addImage(const QString &name, SvImage *image)
{
m_images[name] = image;
}

22
svimageprovider.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef SVIMAGEPROVIDER_H
#define SVIMAGEPROVIDER_H
#include <QtQuick/QQuickImageProvider>
#include <QHash>
#include "svimage.h"
#include <QDebug>
class SvImageProvider : public QQuickImageProvider
{
protected:
QHash<QString, SvImage*> m_images;
public:
SvImageProvider();
virtual QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize);
void addImage(const QString &name, SvImage* image);
};
#endif // SVIMAGEPROVIDER_H

105
svkernelv1.cpp Normal file
View File

@ -0,0 +1,105 @@
#include "svkernelv1.h"
SvKernelV1::SvKernelV1()
{
}
SvKernelV1::~SvKernelV1()
{
}
int SvKernelV1::getPixelColor(int cursor)
{
if (cursor == 0) {
return 0;
}
return ((10 * m_left->getWidth()) / (2.0 * 0.9 * cursor ));
}
int SvKernelV1::diff(int lx, int ly, int rx, int ry)
{
int Red, Green, Blue, color;
int Lvalue = m_left->getPixelValue(lx, ly);
int Rvalue = m_right->getPixelValue(rx, ry);
int dLvalue = m_left->getPixelValue(rx - 1, ry) - Lvalue;
int dRvalue = m_right->getPixelValue(rx - 1, ry) - Rvalue;
int dLsign = dLvalue >= 0 ? 1 : -1;
int dRsign = dRvalue >= 0 ? 1 : -1;
Red = abs(m_left->getPixel(lx, ly, 0) - m_right->getPixel(rx, ry, 0));
Green = abs(m_left->getPixel(lx, ly, 1) - m_right->getPixel(rx, ry, 1));
Blue = abs(m_left->getPixel(lx, ly, 2) - m_right->getPixel(rx, ry, 2));
color = abs(Green - Red) + abs(Blue - Green);
return ((Green + Red + Blue) +
color << 2) + (dLsign == dRsign ? 0 : 100);
}
int SvKernelV1::match(int x, int y, int j)
{
int error = 0;
int ms = 5;
int c = diff(x, y, x + j, y),
l = 0, r = 0, t = 0, b = 0;
error = c;
for (int i = 1; i <= ms; i++) {
l += diff(x - i, y, x + j - i, y);
r += diff(x + i, y, x + j + i, y);
t += diff(x, y - i, x + j, y - i);
b += diff(x, y + i, x + j, y + i);
}
error += l > r ? r : l;
error += t > b ? b : t;
//error += l + r + b + t;
return error;
}
void SvKernelV1::exec(int line)
{
unsigned int x;
int cursor, closest, tmp;
int minErrorValue, tmpSmoothed, matched;
int dist;
cursor = 0;
for (x = 0; x < m_result->getWidth(); x+=1) {
closest = -1; minErrorValue = -1;matched=0;
minErrorValue=-1;
for (int i = 1; i < m_windowSize; i++) {
dist = (abs(cursor - i));
tmp = match(x, line, i);
tmpSmoothed = tmp;
if (tmpSmoothed < minErrorValue || minErrorValue == -1) {
minErrorValue = tmpSmoothed;
closest = i;
matched = 1;
} else if (tmpSmoothed == minErrorValue) {
if (abs(cursor - i) < abs(cursor - closest)) {
closest = i;
matched++;
}
}
}
if (matched == 1) {
cursor = closest;
}
m_result->putGrayPixel(x/* + cursor*/, line, getPixelColor(cursor));
}
}

23
svkernelv1.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef SVKERNELV1_H
#define SVKERNELV1_H
#include "svabstractkernel.h"
class SvKernelV1: public SvAbstractKernel
{
protected:
int m_windowSize = 160;
public:
void exec(int line) override;
SvKernelV1();
virtual ~SvKernelV1();
protected:
int getPixelColor(int cursor);
int diff(int lx, int ly, int rx, int ry);
int match(int x, int y, int i);
};
#endif // SVKERNELV1_H

99
svkernelv2.cpp Normal file
View File

@ -0,0 +1,99 @@
#include "svkernelv2.h"
SvKernelV2::SvKernelV2()
{
}
SvKernelV2::~SvKernelV2()
{
}
int SvKernelV2::rgbDiff(QRgb left, QRgb right)
{
QColor cLeft(left);
QColor cRight(right);
int leftDiff = max(qBlue(left), qRed(left), qGreen(left)) -
min(qBlue(left), qRed(left), qGreen(left));
int rightDiff = max(qBlue(right), qRed(right), qGreen(right)) -
min(qBlue(right), qRed(right), qGreen(right));
int minDiff= leftDiff < rightDiff ? rightDiff : leftDiff;
int diff = cLeft.value() - cRight.value();
int hsvDiff = minDiff > 70 ? abs(cLeft.hsvHue() - cRight.hsvHue()) : 0;
if (hsvDiff > 180) {
hsvDiff = 360 - hsvDiff;
}
int dsign = sign(diff);
dsign = dsign == 0 ? 1 : dsign;
return /*dsign * ((rightDiff - leftDiff)>>2) + */diff /*+ (hsvDiff > 5 ? dsign * 10 : 0)*/;
}
void SvKernelV2::exec(int line)
{
QRgb vtop, top, right, bottom, vbottom, _xy, xy;
int __dX, _dX, dX, dX_,
__dY, _dY, dY, dY_;
int value;
for (int x = 0; x < m_result->getWidth(); x++) {
value = 0;
vtop = m_left->getPixelRGB(x - 1, line - 3);
top = m_left->getPixelRGB(x - 1, line - 2);
right = m_left->getPixelRGB(x, line - 1);
bottom = m_left->getPixelRGB(x - 1, line);
vbottom = m_left->getPixelRGB(x - 1, line + 1);
xy = m_left->getPixelRGB(x - 1, line - 1);
dX_ = rgbDiff(_xy, right);
dY_ = rgbDiff(vtop, top);
dY = rgbDiff(top, _xy);
_dY = rgbDiff(_xy, bottom);
__dY = rgbDiff(bottom, vbottom);
if ( dX >= _dX && dX > dX_ ||
dX <= _dX && dX < dX_) {
if (dX == _dX) {
if (dX > dX_ && _dX > __dX ||
dX < dX_ && _dX < __dX) {
value += abs(dX);
}
} else {
value += abs(dX);
}
}
if ( dY >= _dY && dY > dY_ ||
dY <= _dY && dY < dY_) {
if (dY == _dY) {
if (dY > dY_ && _dY > __dY ||
dY < dY_ && _dY < __dY) {
value += abs(dY);
}
} else {
value += abs(dY);
}
}
if (value > 0) {
m_result->putGrayPixel(x - 1, line - 1, value);
}
__dX = _dX;
_dX = dX;
dX = dX_;
_xy = right;
}
}

19
svkernelv2.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef SVKERNELV2_H
#define SVKERNELV2_H
#include "svabstractkernel.h"
#include <QDebug>
#define sign(a) (a == 0 ? 0 : (a > 0 ? 1 : -1))
#define max(a,b,c) (a > b ? (a > c ? a : c) : (b > c ? b : c))
#define min(a,b,c) (a < b ? (a < c ? a : c) : (b < c ? b : c))
class SvKernelV2: public SvAbstractKernel
{
public:
SvKernelV2();
virtual ~SvKernelV2();
void exec(int line) override;
int rgbDiff(QRgb left, QRgb right);
};
#endif // SVKERNELV2_H

5
svobject.cpp Normal file
View File

@ -0,0 +1,5 @@
#include "svobject.h"
SvObject::SvObject()
{
}

15
svobject.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef SVOBJECT_H
#define SVOBJECT_H
#include "svfigure.h"
class SvObject
{
protected:
SvFigure *m_figures;
public:
SvObject();
};
#endif // SVOBJECT_H

5
svpoint.cpp Normal file
View File

@ -0,0 +1,5 @@
#include "svpoint.h"
SvPoint::SvPoint()
{
}

34
svpoint.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef SVPOINT_H
#define SVPOINT_H
#include "svsimplepoint.h"
#include "svcurve.h"
class SvCurve;
class SvPoint: public SvSimplePoint
{
public:
enum Sides {
TOP,
BOTTOM,
RIGHT,
LEFT
};
enum FlowType {
HORIZONTAL,
VERTICAL,
SLASH,
BACK_SLASH
};
protected:
SvCurve* m_curves;
FlowType m_type;
public:
SvPoint();
};
#endif // SVPOINT_H

71
svprocessor.cpp Normal file
View File

@ -0,0 +1,71 @@
#include "svprocessor.h"
SvProcessor::SvProcessor(QObject *parent):
QObject(parent)
{
}
SvProcessor::SvProcessor(SvImage* left, SvImage* right, SvImage* result, int numberOfWorkers, int version)
{
unsigned int i;
if (version == 1) {
m_kernel = new SvKernelV1();
} else if (version == 2) {
m_kernel = new SvKernelV2();
}
m_kernel->setLeftImage(left);
m_kernel->setRightImage(right);
m_kernel->setResultImage(result);
m_numberOfWorkers = numberOfWorkers;
m_workers = new SvWorker[m_numberOfWorkers];
m_threads = new QThread[m_numberOfWorkers];
for (i = 0; i < m_numberOfWorkers; i++) {
m_workers[i].setId(i);
m_workers[i].setKernel(m_kernel);
m_workers[i].moveToThread(&m_threads[i]);
connect(&m_threads[i], &QThread::started, &m_workers[i], &SvWorker::start);
connect(&m_workers[i], &SvWorker::finished, this, &SvProcessor::workerFinished);
}
for (i = 0; i < result->getHeight(); i++) {
m_workers[i % m_numberOfWorkers].addTask(i);
}
}
SvProcessor::~SvProcessor()
{
delete m_kernel;
delete[] m_workers;
}
void SvProcessor::workerFinished(int workerId)
{
qDebug() << "worker " << workerId << " finished";
m_workersFinished++;
if (m_workersFinished == m_numberOfWorkers) {
qDebug() << "finished";
emit finished(time(NULL) - m_startTime);
}
}
void SvProcessor::start()
{
unsigned int i;
m_startTime = time(NULL);
m_workersFinished = 0;
for (i = 0; i < m_numberOfWorkers; i++) {
m_threads[i].start(QThread::HighestPriority);
}
}
void SvProcessor::stop()
{
emit stopped(time(NULL) - m_startTime);
}

47
svprocessor.h Normal file
View File

@ -0,0 +1,47 @@
#ifndef SVPROCESSOR_H
#define SVPROCESSOR_H
#include <time.h>
#include<QObject>
#include<QThread>
#include<QDebug>
#include "svimage.h"
#include "svworker.h"
#include "svabstractkernel.h"
#include "svkernelv1.h"
#include "svkernelv2.h"
class SvProcessor: public QObject
{
Q_OBJECT
protected:
QThread* m_threads;
SvWorker* m_workers;
SvAbstractKernel* m_kernel;
unsigned int m_numberOfWorkers;
unsigned int m_workersFinished;
unsigned int m_startTime;
public:
explicit SvProcessor(QObject *parent = 0);
SvProcessor(SvImage *left, SvImage *right, SvImage *result, int numberOfWorkers = 1, int version = 1);
~SvProcessor();
void execute();
protected slots:
void workerFinished(int workerId);
public slots:
void start();
void stop();
signals:
void started();
void finished(int elapsedTime);
void stopped(int elapsedTime);
};
#endif // SVPROCESSOR_H

5
svsimplepoint.cpp Normal file
View File

@ -0,0 +1,5 @@
#include "svsimplepoint.h"
SvSimplePoint::SvSimplePoint()
{
}

23
svsimplepoint.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef SVSIMPLEPOINT_H
#define SVSIMPLEPOINT_H
class SvSimplePoint
{
protected:
int m_px, m_py, m_pz;
public:
int x() {return m_px;}
int y() {return m_py;}
int z() {return m_pz;}
int setX(int px) {return m_px = px;}
int setY(int py) {return m_py = py;}
int setZ(int pz) {return m_pz = pz;}
SvSimplePoint();
};
#endif // SVSIMPLEPOINT_H

26
svworker.cpp Normal file
View File

@ -0,0 +1,26 @@
#include "svworker.h"
SvWorker::SvWorker(QObject *parent) :
QObject(parent)
{
}
SvWorker::SvWorker(SvAbstractKernel* kernel)
{
m_kernel = kernel;
}
void SvWorker::stop()
{
}
void SvWorker::start()
{
for (int i: m_tasks) {
m_kernel->exec(i);
}
emit finished(m_id);
}

36
svworker.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef SVWORKER_H
#define SVWORKER_H
#include <QObject>
#include <QList>
#include "svabstractkernel.h"
#include "svimage.h"
class SvWorker : public QObject
{
Q_OBJECT
protected:
int m_id;
SvAbstractKernel* m_kernel;
QList<unsigned int> m_tasks;
public:
explicit SvWorker(QObject *parent = 0);
SvWorker(SvAbstractKernel* kernel);
void setId(int id) {m_id = id;}
void addTask(int line) {m_tasks << line;}
void setKernel(SvAbstractKernel* kernel) {m_kernel = kernel;}
signals:
void finished(int id);
public slots:
void stop();
void start();
};
#endif // SVWORKER_H