feat(ImageShow-&-Mask): for crop rotate ... image
BREAKING CHANGE:
This commit is contained in:
parent
99ae37aac6
commit
60ed3faf63
BIN
public/test.jpg
BIN
public/test.jpg
Binary file not shown.
|
Before Width: | Height: | Size: 509 KiB After Width: | Height: | Size: 85 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 509 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.1 MiB |
|
|
@ -1,21 +1,26 @@
|
||||||
<script>
|
<script>
|
||||||
import { v4 as uuidv4 } from "uuid";
|
|
||||||
import { onMount, onDestroy } from "svelte";
|
import { onMount, onDestroy } from "svelte";
|
||||||
|
|
||||||
import Navbar from "./Navbar.svelte";
|
import Navbar from "./Navbar.svelte";
|
||||||
|
import Mask from "./Mask.svelte";
|
||||||
|
import { ImageProcess } from "./utils";
|
||||||
|
|
||||||
const cv = window.cv;
|
const cv = window.cv;
|
||||||
|
let image_process = new ImageProcess();
|
||||||
|
|
||||||
export let url = "test.jpg";
|
export let url = "test.jpg";
|
||||||
|
|
||||||
let canvas_dom;
|
let canvas_dom;
|
||||||
let canvas;
|
let resize_tag;
|
||||||
let image;
|
let image;
|
||||||
|
|
||||||
|
let image_for_show;
|
||||||
let window_width;
|
let window_width;
|
||||||
let window_height;
|
let window_height;
|
||||||
let canvas_width = 0;
|
let canvas_width = 0;
|
||||||
let canvas_height = 0;
|
let canvas_height = 0;
|
||||||
let active;
|
|
||||||
|
let mask_tag = false;
|
||||||
|
|
||||||
function LabelItem(label, items) {
|
function LabelItem(label, items) {
|
||||||
this.label = label;
|
this.label = label;
|
||||||
|
|
@ -26,7 +31,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function OperationItem(name, icon, handler = null) {
|
function OperationItem(name, icon, handler = null) {
|
||||||
this.id = uuidv4();
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.icon = icon;
|
this.icon = icon;
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
|
|
@ -38,12 +42,42 @@
|
||||||
["重新采集", "mdi mdi-reply-outline"],
|
["重新采集", "mdi mdi-reply-outline"],
|
||||||
]),
|
]),
|
||||||
new LabelItem("图像操作", [
|
new LabelItem("图像操作", [
|
||||||
["向左旋转", "mdi mdi-file-rotate-left-outline", () => {}],
|
[
|
||||||
["向右旋转", "mdi mdi-file-rotate-right-outline"],
|
"向左旋转",
|
||||||
|
"mdi mdi-file-rotate-left-outline",
|
||||||
|
() => {
|
||||||
|
image_process.turn_left();
|
||||||
|
cv.rotate(image_for_show, image_for_show, 0);
|
||||||
|
show_image();
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"向右旋转",
|
||||||
|
"mdi mdi-file-rotate-right-outline",
|
||||||
|
() => {
|
||||||
|
image_process.turn_right();
|
||||||
|
cv.rotate(image_for_show, image_for_show, 2);
|
||||||
|
show_image();
|
||||||
|
},
|
||||||
|
],
|
||||||
["文本加强", "mdi mdi-image-filter-center-focus-strong"],
|
["文本加强", "mdi mdi-image-filter-center-focus-strong"],
|
||||||
["裁剪", "mdi mdi-crop"],
|
[
|
||||||
["滚轮缩放", "mdi mdi-loupe"],
|
"裁剪",
|
||||||
["取消", "mdi mdi-alpha-x-circle-outline"],
|
"mdi mdi-crop",
|
||||||
|
() => {
|
||||||
|
console.log(mask_tag);
|
||||||
|
mask_tag = mask_tag ? false : true;
|
||||||
|
console.log(mask_tag);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"还原",
|
||||||
|
"mdi mdi-alpha-x-circle-outline",
|
||||||
|
() => {
|
||||||
|
image_process.recover();
|
||||||
|
init_canvas();
|
||||||
|
},
|
||||||
|
],
|
||||||
]),
|
]),
|
||||||
new LabelItem("文件操作", [
|
new LabelItem("文件操作", [
|
||||||
["保存到本地", "mdi mdi-content-save-outline"],
|
["保存到本地", "mdi mdi-content-save-outline"],
|
||||||
|
|
@ -57,108 +91,153 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function on_window_resize() {
|
function on_window_resize() {
|
||||||
/*setTimeout(() => {
|
if (resize_tag) {
|
||||||
let scale = Math.min(
|
clearTimeout(resize_tag);
|
||||||
canvas_height / image.height,
|
|
||||||
canvas_width / image.width
|
|
||||||
);
|
|
||||||
|
|
||||||
canvas.setWidth(image.width * scale);
|
|
||||||
canvas.setHeight(image.height * scale);
|
|
||||||
|
|
||||||
image.scale(scale);
|
|
||||||
}, 50);*/
|
|
||||||
}
|
|
||||||
|
|
||||||
function rotate(img, angle) {
|
|
||||||
let dst = new cv.Mat();
|
|
||||||
let dsize = new cv.Size(img.rows, img.cols);
|
|
||||||
let center = new cv.Point(img.cols / 2, img.rows / 2);
|
|
||||||
let M = cv.getRotationMatrix2D(center, angle, 1);
|
|
||||||
cv.warpAffine(
|
|
||||||
img,
|
|
||||||
dst,
|
|
||||||
M,
|
|
||||||
dsize,
|
|
||||||
cv.INTER_LINEAR,
|
|
||||||
cv.BORDER_CONSTANT,
|
|
||||||
new cv.Scalar()
|
|
||||||
);
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
|
|
||||||
function resize(img, scale) {
|
|
||||||
let dst = new cv.Mat();
|
|
||||||
let dsize = new cv.Size(scale * img.cols, scale * img.rows);
|
|
||||||
|
|
||||||
cv.resize(img, dst, dsize, 0, 0, cv.INTER_AREA);
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
|
|
||||||
function show_image(img, { option = {} }) {
|
|
||||||
if (option.hasOwnProperty("angle")) {
|
|
||||||
}
|
}
|
||||||
|
resize_tag = setTimeout(function () {
|
||||||
let dst = img.clone();
|
image_process.roi_init();
|
||||||
for (const [key, value] of Object.entries(option)) {
|
if (image) {
|
||||||
if (key === "resize") {
|
let pre_scale = Math.min(
|
||||||
let scale = Math.min(
|
canvas_height / image.rows,
|
||||||
canvas_height / image.height,
|
canvas_width / image.cols
|
||||||
canvas_width / image.width
|
|
||||||
);
|
);
|
||||||
dst = resize(dst, scale);
|
let pre_dsize = new cv.Size(
|
||||||
console.log(dst);
|
pre_scale * image.cols,
|
||||||
}
|
pre_scale * image.rows
|
||||||
if (key === "rotate") {
|
);
|
||||||
dst = rotate
|
cv.resize(
|
||||||
|
image_for_show,
|
||||||
|
image_for_show,
|
||||||
|
pre_dsize,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
cv.INTER_AREA
|
||||||
|
);
|
||||||
|
|
||||||
|
show_image();
|
||||||
}
|
}
|
||||||
|
}, 40);
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_image() {
|
||||||
|
mask_tag = false;
|
||||||
|
let dst = new cv.Mat();
|
||||||
|
console.time("image show");
|
||||||
|
if (image_process.roi_tag) {
|
||||||
|
dst = image_for_show.roi(image_process.ROI_rect);
|
||||||
|
} else {
|
||||||
|
dst = image_for_show.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let scale = Math.min(canvas_height / dst.rows, canvas_width / dst.cols);
|
||||||
|
let dsize = new cv.Size(scale * dst.cols, scale * dst.rows);
|
||||||
|
cv.resize(dst, dst, dsize, 0, 0, cv.INTER_AREA);
|
||||||
|
|
||||||
cv.imshow("canvas", dst);
|
cv.imshow("canvas", dst);
|
||||||
dst.delete;
|
|
||||||
|
console.timeEnd("image show");
|
||||||
|
dst.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function init_canvas() {
|
async function init_canvas() {
|
||||||
let img = new Image();
|
let img = new Image();
|
||||||
|
image_for_show = new cv.Mat();
|
||||||
img.src = url;
|
img.src = url;
|
||||||
img.onload = function () {
|
img.onload = function () {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
image = cv.imread(img);
|
image = cv.imread(img);
|
||||||
let scale = Math.min(
|
let pre_scale = Math.min(
|
||||||
canvas_height / image.rows,
|
canvas_height / image.rows,
|
||||||
canvas_width / image.cols
|
canvas_width / image.cols
|
||||||
);
|
);
|
||||||
let dst = new cv.Mat();
|
let pre_dsize = new cv.Size(
|
||||||
let dsize = new cv.Size(scale * image.cols, scale * image.rows);
|
pre_scale * image.cols,
|
||||||
|
pre_scale * image.rows
|
||||||
|
);
|
||||||
|
cv.resize(image, image_for_show, pre_dsize, 0, 0, cv.INTER_AREA);
|
||||||
|
|
||||||
cv.resize(image, dst, dsize, 0, 0, cv.INTER_AREA);
|
show_image();
|
||||||
cv.imshow("canvas", dst);
|
|
||||||
/* image = new fabric.Image(img);
|
|
||||||
let scale = Math.min(
|
|
||||||
canvas_height / image.height,
|
|
||||||
canvas_width / image.width
|
|
||||||
);
|
|
||||||
|
|
||||||
image.scale(scale);
|
|
||||||
canvas.setWidth(image.width * scale);
|
|
||||||
canvas.setHeight(image.height * scale);
|
|
||||||
canvas.add(image);
|
|
||||||
console.log(image);*/
|
|
||||||
}, 50);
|
}, 50);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function wheel_event_handler(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let mouse_point = new cv.Point(
|
||||||
|
e.clientX - canvas_dom.offsetLeft,
|
||||||
|
e.clientY - canvas_dom.offsetTop
|
||||||
|
);
|
||||||
|
image_process.roi(
|
||||||
|
image_for_show.rows,
|
||||||
|
image_for_show.cols,
|
||||||
|
mouse_point,
|
||||||
|
e.deltaY
|
||||||
|
);
|
||||||
|
show_image();
|
||||||
|
}
|
||||||
|
|
||||||
|
function keyboard_move_roi(event) {
|
||||||
|
if (event.shiftKey && event.altKey && event.ctrlKey) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (event.keyCode > 40 || event.keyCode < 37) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
switch (event.key) {
|
||||||
|
case "ArrowUp":
|
||||||
|
image_process.roi_up();
|
||||||
|
break;
|
||||||
|
case "ArrowDown":
|
||||||
|
image_process.roi_down(image_for_show.rows);
|
||||||
|
break;
|
||||||
|
case "ArrowLeft":
|
||||||
|
image_process.roi_left();
|
||||||
|
break;
|
||||||
|
case "ArrowRight":
|
||||||
|
image_process.roi_right(image_for_show.cols);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
show_image();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*function mouse_move_roi(event) {
|
||||||
|
if (event.type == "mousedown") {
|
||||||
|
roi_move_tag = true;
|
||||||
|
} else if (event.type == "mouseup") {
|
||||||
|
roi_move_tag = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function drag_roi(event) {
|
||||||
|
if (roi_move_tag) {
|
||||||
|
console.log(event);
|
||||||
|
let delta = {
|
||||||
|
x: event.clientX - mouse_move.x,
|
||||||
|
y: event.clientY - mouse_move.y,
|
||||||
|
};
|
||||||
|
image_process.roi_move(delta);
|
||||||
|
mouse_move = {
|
||||||
|
x: event.clientX,
|
||||||
|
y: event.clientY,
|
||||||
|
};
|
||||||
|
show_image();
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
canvas_height = window_height - 64;
|
canvas_height = window_height - 64;
|
||||||
canvas_width = (window_width * 13) / 16;
|
canvas_width = (window_width * 13) / 16;
|
||||||
init_canvas();
|
init_canvas();
|
||||||
console.log(window);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
onDestroy(async () => {
|
onDestroy(async () => {
|
||||||
if (image.delete) {
|
if (image.delete) {
|
||||||
image.delete();
|
image.delete();
|
||||||
}
|
}
|
||||||
|
if (image_for_show.delete) {
|
||||||
|
image_for_show.delete();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -166,6 +245,7 @@
|
||||||
bind:innerHeight={window_height}
|
bind:innerHeight={window_height}
|
||||||
bind:innerWidth={window_width}
|
bind:innerWidth={window_width}
|
||||||
on:resize={on_window_resize}
|
on:resize={on_window_resize}
|
||||||
|
on:keydown={keyboard_move_roi}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="disable-selection">
|
<div class="disable-selection">
|
||||||
|
|
@ -181,9 +261,7 @@
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
class:is-active={active === item.id}
|
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
active = item.id;
|
|
||||||
if (item.handler) {
|
if (item.handler) {
|
||||||
item.handler();
|
item.handler();
|
||||||
}
|
}
|
||||||
|
|
@ -201,7 +279,16 @@
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
<div class="column" style="text-align:center">
|
<div class="column" style="text-align:center">
|
||||||
<canvas bind:this={canvas_dom} id="canvas" />
|
<div>
|
||||||
|
{#if mask_tag}
|
||||||
|
<Mask {canvas_dom} />
|
||||||
|
{/if}
|
||||||
|
<canvas
|
||||||
|
bind:this={canvas_dom}
|
||||||
|
id="canvas"
|
||||||
|
on:wheel={wheel_event_handler}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,12 @@
|
||||||
<script>
|
<script>
|
||||||
import { v4 as uuidv4 } from "uuid";
|
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
|
|
||||||
import { fabric } from "fabric";
|
import { fabric } from "fabric";
|
||||||
|
|
||||||
import Navbar from "./Navbar.svelte";
|
import Navbar from "./Navbar.svelte";
|
||||||
import { ImageProcessing } from "./utils";
|
|
||||||
|
|
||||||
export let url = "test.jpg";
|
export let url = "test.jpg";
|
||||||
|
|
||||||
let img_process = new ImageProcessing();
|
|
||||||
|
|
||||||
let canvas_dom;
|
let canvas_dom;
|
||||||
let canvas;
|
let canvas;
|
||||||
let image;
|
let image;
|
||||||
|
|
@ -18,7 +14,7 @@
|
||||||
let window_height;
|
let window_height;
|
||||||
let canvas_width = 0;
|
let canvas_width = 0;
|
||||||
let canvas_height = 0;
|
let canvas_height = 0;
|
||||||
let active;
|
let resize_tag;
|
||||||
|
|
||||||
function LabelItem(label, items) {
|
function LabelItem(label, items) {
|
||||||
this.label = label;
|
this.label = label;
|
||||||
|
|
@ -29,7 +25,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function OperationItem(name, icon, handler = null) {
|
function OperationItem(name, icon, handler = null) {
|
||||||
this.id = uuidv4();
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.icon = icon;
|
this.icon = icon;
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
|
|
@ -39,20 +34,34 @@
|
||||||
new LabelItem("采集操作", [
|
new LabelItem("采集操作", [
|
||||||
["确认并返回", "mdi mdi-checkbox-marked-circle-outline"],
|
["确认并返回", "mdi mdi-checkbox-marked-circle-outline"],
|
||||||
["重新采集", "mdi mdi-reply-outline"],
|
["重新采集", "mdi mdi-reply-outline"],
|
||||||
["取消", "mdi mdi-alpha-x-circle-outline"],
|
|
||||||
]),
|
]),
|
||||||
new LabelItem("图像操作", [
|
new LabelItem("图像操作", [
|
||||||
[
|
[
|
||||||
"向左旋转",
|
"向左旋转",
|
||||||
"mdi mdi-file-rotate-left-outline",
|
"mdi mdi-file-rotate-left-outline",
|
||||||
() => {
|
() => {
|
||||||
|
console.log("rotate 90");
|
||||||
image.rotate(90);
|
image.rotate(90);
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
["向右旋转", "mdi mdi-file-rotate-right-outline"],
|
[
|
||||||
|
"向右旋转",
|
||||||
|
"mdi mdi-file-rotate-right-outline",
|
||||||
|
() => {
|
||||||
|
console.log("rotate 270");
|
||||||
|
|
||||||
|
image.rotate(270);
|
||||||
|
},
|
||||||
|
],
|
||||||
["文本加强", "mdi mdi-image-filter-center-focus-strong"],
|
["文本加强", "mdi mdi-image-filter-center-focus-strong"],
|
||||||
["裁剪", "mdi mdi-crop"],
|
["裁剪", "mdi mdi-crop"],
|
||||||
["滚轮缩放", "mdi mdi-loupe"],
|
[
|
||||||
|
"还原",
|
||||||
|
"mdi mdi-alpha-x-circle-outline",
|
||||||
|
() => {
|
||||||
|
init_canvas();
|
||||||
|
},
|
||||||
|
],
|
||||||
]),
|
]),
|
||||||
new LabelItem("文件操作", [
|
new LabelItem("文件操作", [
|
||||||
["保存到本地", "mdi mdi-content-save-outline"],
|
["保存到本地", "mdi mdi-content-save-outline"],
|
||||||
|
|
@ -66,7 +75,10 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function resize() {
|
function resize() {
|
||||||
setTimeout(() => {
|
if (resize_tag) {
|
||||||
|
clearTimeout(resize_tag);
|
||||||
|
}
|
||||||
|
resize_tag = setTimeout(() => {
|
||||||
let scale = Math.min(
|
let scale = Math.min(
|
||||||
canvas_height / image.height,
|
canvas_height / image.height,
|
||||||
canvas_width / image.width
|
canvas_width / image.width
|
||||||
|
|
@ -74,7 +86,7 @@
|
||||||
|
|
||||||
canvas.setWidth(image.width * scale);
|
canvas.setWidth(image.width * scale);
|
||||||
canvas.setHeight(image.height * scale);
|
canvas.setHeight(image.height * scale);
|
||||||
|
image.rotate(90);
|
||||||
image.scale(scale);
|
image.scale(scale);
|
||||||
}, 50);
|
}, 50);
|
||||||
}
|
}
|
||||||
|
|
@ -85,20 +97,17 @@
|
||||||
img.onload = async function () {
|
img.onload = async function () {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
canvas = new fabric.StaticCanvas(canvas_dom);
|
canvas = new fabric.StaticCanvas(canvas_dom);
|
||||||
setTimeout(() => {
|
image = new fabric.Image(img);
|
||||||
image = new fabric.Image(img);
|
let scale = Math.min(
|
||||||
let scale = Math.min(
|
canvas_height / image.height,
|
||||||
canvas_height / image.height,
|
canvas_width / image.width
|
||||||
canvas_width / image.width
|
);
|
||||||
);
|
|
||||||
|
|
||||||
image.scale(scale);
|
image.scale(scale);
|
||||||
canvas.setWidth(image.width * scale);
|
canvas.setWidth(image.width * scale);
|
||||||
canvas.setHeight(image.height * scale);
|
canvas.setHeight(image.height * scale);
|
||||||
canvas.add(image);
|
canvas.add(image);
|
||||||
console.log(image);
|
}, 50);
|
||||||
}, 50);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,7 +115,6 @@
|
||||||
canvas_height = window_height - 64;
|
canvas_height = window_height - 64;
|
||||||
canvas_width = (window_width * 13) / 16;
|
canvas_width = (window_width * 13) / 16;
|
||||||
init_canvas();
|
init_canvas();
|
||||||
console.log(window)
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -129,9 +137,7 @@
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
class:is-active={active === item.id}
|
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
active = item.id;
|
|
||||||
if (item.handler) {
|
if (item.handler) {
|
||||||
item.handler();
|
item.handler();
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,283 @@
|
||||||
|
<script>
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
|
||||||
|
// 应该确定四个点
|
||||||
|
export let canvas_dom;
|
||||||
|
|
||||||
|
let mask_top = canvas_dom.offsetTop;
|
||||||
|
let mask_left = canvas_dom.offsetLeft;
|
||||||
|
let mask_width = canvas_dom.clientWidth;
|
||||||
|
let mask_height = canvas_dom.clientHeight;
|
||||||
|
|
||||||
|
let cursor = "default";
|
||||||
|
|
||||||
|
let crop_tag = false;
|
||||||
|
|
||||||
|
let crop_area = -1;
|
||||||
|
|
||||||
|
let mask_rects = [];
|
||||||
|
|
||||||
|
function get_crop_rect(rects) {
|
||||||
|
if (rects.length == 9) {
|
||||||
|
return {
|
||||||
|
x: rects[4][0] - mask_left,
|
||||||
|
y: rects[4][1] - mask_top,
|
||||||
|
width: rects[4][2],
|
||||||
|
height: rects[4][3],
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export let crop_rect = {};
|
||||||
|
|
||||||
|
let crop_rect_with_offset = {
|
||||||
|
x: mask_left + mask_width * 0.2,
|
||||||
|
y: mask_top,
|
||||||
|
width: mask_width * 0.6,
|
||||||
|
height: mask_height * 0.6,
|
||||||
|
};
|
||||||
|
|
||||||
|
$: {
|
||||||
|
crop_rect = get_crop_rect(mask_rects);
|
||||||
|
console.log(crop_rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
function init_mask_rects() {
|
||||||
|
// TODO:
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
mask_left,
|
||||||
|
mask_top,
|
||||||
|
crop_rect_with_offset.x - mask_left,
|
||||||
|
crop_rect_with_offset.y - mask_top,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
crop_rect_with_offset.x,
|
||||||
|
mask_top,
|
||||||
|
crop_rect_with_offset.width,
|
||||||
|
crop_rect_with_offset.y - mask_top,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
crop_rect_with_offset.x + crop_rect_with_offset.width,
|
||||||
|
mask_top,
|
||||||
|
mask_left + mask_width,
|
||||||
|
crop_rect_with_offset.y - mask_top,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
mask_left,
|
||||||
|
crop_rect_with_offset.y,
|
||||||
|
crop_rect_with_offset.x - mask_left,
|
||||||
|
crop_rect_with_offset.y - mask_top,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
crop_rect_with_offset.x,
|
||||||
|
crop_rect_with_offset.y,
|
||||||
|
crop_rect_with_offset.width,
|
||||||
|
crop_rect_with_offset.height,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function _set_crop_rect(e) {
|
||||||
|
if (crop_area < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (crop_area) {
|
||||||
|
case 0:
|
||||||
|
console.log("mask_rects.4:" + mask_rects[4]);
|
||||||
|
crop_rect_with_offset.x = e.clientX;
|
||||||
|
crop_rect_with_offset.y = e.clientY;
|
||||||
|
crop_rect_with_offset.width =
|
||||||
|
mask_rects[4][2] - (mask_rects[4][0] - e.clientX);
|
||||||
|
crop_rect_with_offset.height =
|
||||||
|
mask_rects[4][3] - (mask_rects[4][1] - e.clientY);
|
||||||
|
mask_rects = init_mask_rects();
|
||||||
|
return;
|
||||||
|
/*mask_rects[4][2] = r4[3] - (r4[0] - e.clientX);
|
||||||
|
mask_rects[4][3] = r4[4] - (r4[1] - e.clientY);
|
||||||
|
case 1:
|
||||||
|
mask_rects[4][1] = e.clientY;
|
||||||
|
mask_rects[4][3] = r4[4] - (r4[1] - e.clientY);*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_crop_rect(e, i) {
|
||||||
|
console.log(crop_tag);
|
||||||
|
if (crop_tag) {
|
||||||
|
_set_crop_rect(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (i != 4) {
|
||||||
|
crop_area = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
e.clientX - mask_rects[4][1] <= mask_width * 0.01 &&
|
||||||
|
e.clientY - mask_rects[4][0] <= mask_height * 0.01
|
||||||
|
) {
|
||||||
|
cursor = "nwse-resize";
|
||||||
|
crop_area = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.clientY - mask_rects[4][0] <= mask_height * 0.01) {
|
||||||
|
cursor = "ns-resize";
|
||||||
|
crop_area = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
e.clientX - mask_rects[4][1] <= mask_width * 0.01 &&
|
||||||
|
e.clientY - mask_rects[4][0] - mask_rects[4][3] >= -mask_height * 0.01
|
||||||
|
) {
|
||||||
|
cursor = "nesw-resize";
|
||||||
|
crop_area = 2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.clientX - mask_rects[4][1] <= mask_width * 0.01) {
|
||||||
|
cursor = "ew-resize";
|
||||||
|
crop_area = 3;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.clientX - mask_rects[4][1] - mask_rects[4][2] >= -mask_width * 0.01) {
|
||||||
|
cursor = "ew-resize";
|
||||||
|
crop_area = 4;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
e.clientX - mask_rects[4][1] - mask_rects[4][2] >= -mask_width * 0.01 &&
|
||||||
|
e.clientY - mask_rects[4][0] <= mask_height * 0.01
|
||||||
|
) {
|
||||||
|
cursor = "nesw-resize";
|
||||||
|
crop_area = 5;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
e.clientY - mask_rects[4][0] - mask_rects[4][3] >=
|
||||||
|
-mask_height * 0.01
|
||||||
|
) {
|
||||||
|
cursor = "ns-resize";
|
||||||
|
crop_area = 6;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
e.clientX - mask_rects[4][1] - mask_rects[4][2] >= -mask_width * 0.01 &&
|
||||||
|
e.clientY - mask_rects[4][0] - mask_rects[4][3] >= -mask_height * 0.01
|
||||||
|
) {
|
||||||
|
cursor = "nwse-resize";
|
||||||
|
crop_area = 7;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
crop_area = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
for (let i = 0; i < 9; i++) {
|
||||||
|
mask_rects[i] = [
|
||||||
|
mask_top_pos(i),
|
||||||
|
mask_left_pos(i),
|
||||||
|
mask_width_pos(i),
|
||||||
|
mask_height_pos(i),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function mask_top_pos(index) {
|
||||||
|
let k = Math.floor(index / 3);
|
||||||
|
switch (k) {
|
||||||
|
case 0:
|
||||||
|
return mask_top;
|
||||||
|
case 1:
|
||||||
|
return mask_top + mask_height * 0.2;
|
||||||
|
case 2:
|
||||||
|
return mask_top + mask_height * 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mask_left_pos(index) {
|
||||||
|
let k = index % 3;
|
||||||
|
switch (k) {
|
||||||
|
case 0:
|
||||||
|
return mask_left;
|
||||||
|
case 1:
|
||||||
|
return mask_left + mask_width * 0.2;
|
||||||
|
case 2:
|
||||||
|
return mask_left + mask_width * 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mask_width_pos(index) {
|
||||||
|
let k = index % 3;
|
||||||
|
switch (k) {
|
||||||
|
case 0:
|
||||||
|
return mask_width * 0.2;
|
||||||
|
case 1:
|
||||||
|
return mask_width * 0.6;
|
||||||
|
case 2:
|
||||||
|
return mask_width * 0.2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mask_height_pos(index) {
|
||||||
|
let k = Math.floor(index / 3);
|
||||||
|
switch (k) {
|
||||||
|
case 0:
|
||||||
|
return mask_height * 0.2;
|
||||||
|
case 1:
|
||||||
|
return mask_height * 0.6;
|
||||||
|
case 2:
|
||||||
|
return mask_height * 0.2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#each mask_rects as r, i}
|
||||||
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
|
<div
|
||||||
|
class={i != 4 ? "mask" : "mask-center"}
|
||||||
|
style:top={r[0] + "px"}
|
||||||
|
style:left={r[1] + "px"}
|
||||||
|
style:width={r[2] + "px"}
|
||||||
|
style:height={r[3] + "px"}
|
||||||
|
style:cursor
|
||||||
|
on:mousemove={(e) => {
|
||||||
|
set_crop_rect(e, i);
|
||||||
|
}}
|
||||||
|
on:mousedown={() => {
|
||||||
|
if (i == 4) {
|
||||||
|
crop_tag = true;
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
on:mouseup={() => {
|
||||||
|
crop_tag = false;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div class="mask-inner" />
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.mask {
|
||||||
|
position: fixed;
|
||||||
|
background-color: gray;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mask-center {
|
||||||
|
position: fixed;
|
||||||
|
border: 2px solid black;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mask-inner {
|
||||||
|
width: 98%;
|
||||||
|
height: 98%;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
let user;
|
let user;
|
||||||
let guide = new RouterGuide();
|
let guide = new RouterGuide();
|
||||||
|
|
||||||
function logout() {
|
function logout() {
|
||||||
guide.push("/login");
|
guide.push("/login");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
183
src/lib/utils.js
183
src/lib/utils.js
|
|
@ -1,5 +1,8 @@
|
||||||
import procedure from "../assets/Procedure.json";
|
import procedure from "../assets/Procedure.json";
|
||||||
|
|
||||||
|
const cv = window.cv;
|
||||||
|
const move_step = 3;
|
||||||
|
|
||||||
export function Operation(step) {
|
export function Operation(step) {
|
||||||
this.step = step;
|
this.step = step;
|
||||||
|
|
||||||
|
|
@ -18,11 +21,187 @@ export function Operation(step) {
|
||||||
if (!s) {
|
if (!s) {
|
||||||
return procedure.find((e) => e.id === this.step).name;
|
return procedure.find((e) => e.id === this.step).name;
|
||||||
}
|
}
|
||||||
console.log(s);
|
|
||||||
return procedure.find((e) => e.id === s).name;
|
return procedure.find((e) => e.id === s).name;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.get_color = () => {
|
this.get_color = () => {
|
||||||
return procedure.find((e) => e.id === this.step).color;
|
return procedure.find((e) => e.id === this.step).color;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function ImageProcess() {
|
||||||
|
let angle = 0;
|
||||||
|
|
||||||
|
this.roi_tag = false;
|
||||||
|
this.roi_scale_ratio = 1;
|
||||||
|
|
||||||
|
this.rotate_tag = -1;
|
||||||
|
|
||||||
|
this.ROI_rect = new cv.Rect(0, 0, 0, 0);
|
||||||
|
this.crop_rect = null;
|
||||||
|
|
||||||
|
this.recover = () => {
|
||||||
|
angle = 0;
|
||||||
|
this.roi_tag = false;
|
||||||
|
this.roi_scale_ratio = 1;
|
||||||
|
|
||||||
|
this.rotate_tag = -1;
|
||||||
|
|
||||||
|
this.ROI_rect = new cv.Rect(0, 0, 0, 0);
|
||||||
|
this.crop_rect = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.roi_init = () => {
|
||||||
|
this.roi_tag = false;
|
||||||
|
this.roi_scale_ratio = 1;
|
||||||
|
|
||||||
|
this.ROI_rect = new cv.Rect(0, 0, 0, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.roi_move = ({ x, y }) => {
|
||||||
|
if (x >= 0) {
|
||||||
|
this.roi_right(x);
|
||||||
|
} else {
|
||||||
|
this.roi_left(-x);
|
||||||
|
}
|
||||||
|
if (y >= 0) {
|
||||||
|
this.roi_down(y);
|
||||||
|
} else {
|
||||||
|
this.roi_down(-y);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.roi_up = (step = move_step) => {
|
||||||
|
let x = this.ROI_rect.x;
|
||||||
|
let y = this.ROI_rect.y >= step ? this.ROI_rect.y - step : 0;
|
||||||
|
let width = this.ROI_rect.width;
|
||||||
|
let height = this.ROI_rect.height;
|
||||||
|
|
||||||
|
this.ROI_rect = new cv.Rect(x, y, width, height);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.roi_down = (rows, step = move_step) => {
|
||||||
|
let x = this.ROI_rect.x;
|
||||||
|
let y =
|
||||||
|
this.ROI_rect.y <= rows - this.ROI_rect.height - step
|
||||||
|
? this.ROI_rect.y + step
|
||||||
|
: rows - this.ROI_rect.height - step;
|
||||||
|
let width = this.ROI_rect.width;
|
||||||
|
let height = this.ROI_rect.height;
|
||||||
|
this.ROI_rect = new cv.Rect(x, y, width, height);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.roi_left = (step = move_step) => {
|
||||||
|
let x = this.ROI_rect.x >= step ? this.ROI_rect.x - step : 0;
|
||||||
|
let y = this.ROI_rect.y;
|
||||||
|
let width = this.ROI_rect.width;
|
||||||
|
let height = this.ROI_rect.height;
|
||||||
|
|
||||||
|
this.ROI_rect = new cv.Rect(x, y, width, height);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.roi_right = (cols, step = move_step) => {
|
||||||
|
let x =
|
||||||
|
this.ROI_rect.x + this.ROI_rect.width + step <= cols
|
||||||
|
? this.ROI_rect.x + step
|
||||||
|
: cols - this.ROI_rect.width - step;
|
||||||
|
let y = this.ROI_rect.y;
|
||||||
|
let width = this.ROI_rect.width;
|
||||||
|
let height = this.ROI_rect.height;
|
||||||
|
this.ROI_rect = new cv.Rect(x, y, width, height);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.roi = (rows, cols, center, delta_wheel, scale_ratio = 0.05) => {
|
||||||
|
// Transition coordinate system at first.
|
||||||
|
let c_at_image = new cv.Point(
|
||||||
|
center.x * this.roi_scale_ratio + this.ROI_rect.x,
|
||||||
|
center.y * this.roi_scale_ratio + this.ROI_rect.y
|
||||||
|
);
|
||||||
|
|
||||||
|
let ratio = this.roi_scale_ratio + (delta_wheel / 144) * scale_ratio;
|
||||||
|
this.roi_scale_ratio = ratio <= 1 ? ratio : 1;
|
||||||
|
|
||||||
|
if (!this.roi_tag) {
|
||||||
|
this.ROI_rect = new cv.Rect(0, 0, cols, rows);
|
||||||
|
this.roi_tag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let roi_width = cols * this.roi_scale_ratio;
|
||||||
|
let roi_height = rows * this.roi_scale_ratio;
|
||||||
|
|
||||||
|
if (Math.min(roi_width / cols, roi_height / rows) <= 0.3) {
|
||||||
|
this.roi_scale_ratio = 0.3;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let x =
|
||||||
|
c_at_image.x -
|
||||||
|
(c_at_image.x * roi_width) / this.ROI_rect.width +
|
||||||
|
(this.ROI_rect.x * roi_width) / this.ROI_rect.width;
|
||||||
|
let y =
|
||||||
|
c_at_image.y -
|
||||||
|
(c_at_image.y * roi_height) / this.ROI_rect.height +
|
||||||
|
(this.ROI_rect.y * roi_height) / this.ROI_rect.height;
|
||||||
|
|
||||||
|
if (roi_width + x <= cols && roi_height + y <= rows) {
|
||||||
|
this.ROI_rect = new cv.Rect(
|
||||||
|
x >= 0 ? x : 0,
|
||||||
|
y >= 0 ? y : 0,
|
||||||
|
roi_width,
|
||||||
|
roi_height
|
||||||
|
);
|
||||||
|
} else if (roi_width + x <= cols && roi_height + y >= rows) {
|
||||||
|
this.ROI_rect = new cv.Rect(
|
||||||
|
x >= 0 ? x : 0,
|
||||||
|
rows - roi_height,
|
||||||
|
roi_width,
|
||||||
|
roi_height
|
||||||
|
);
|
||||||
|
} else if (roi_width + x >= cols && roi_height + y >= rows) {
|
||||||
|
this.ROI_rect = new cv.Rect(
|
||||||
|
cols - roi_width,
|
||||||
|
rows - roi_height,
|
||||||
|
roi_width,
|
||||||
|
roi_height
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.turn_left = () => {
|
||||||
|
this.roi_init();
|
||||||
|
angle = angle + 270;
|
||||||
|
let k = angle % 360;
|
||||||
|
|
||||||
|
if (k == 90) {
|
||||||
|
this.rotate_tag = 0;
|
||||||
|
} else if (k == 180) {
|
||||||
|
this.rotate_tag = 1;
|
||||||
|
} else if (k == 270) {
|
||||||
|
this.rotate_tag = 2;
|
||||||
|
} else {
|
||||||
|
this.rotate_tag = -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.turn_right = () => {
|
||||||
|
this.roi_init();
|
||||||
|
|
||||||
|
angle = angle + 90;
|
||||||
|
let k = angle % 360;
|
||||||
|
if (k == 90) {
|
||||||
|
this.rotate_tag = 0;
|
||||||
|
} else if (k == 180) {
|
||||||
|
this.rotate_tag = 1;
|
||||||
|
} else if (k == 270) {
|
||||||
|
this.rotate_tag = 2;
|
||||||
|
} else {
|
||||||
|
this.rotate_tag = -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.set_roi = (rect) => {
|
||||||
|
this.ROI_rect = rect;
|
||||||
|
};
|
||||||
|
this.set_crop_roi = (rect) => {
|
||||||
|
this.crop_rect = rect;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { setContext } from "svelte";
|
||||||
import Main from "../lib/Main.svelte";
|
import Main from "../lib/Main.svelte";
|
||||||
import Login from "../lib/Login.svelte";
|
import Login from "../lib/Login.svelte";
|
||||||
import Image from "../lib/ImageShow.svelte";
|
import Image from "../lib/ImageShow.svelte";
|
||||||
|
// import Image from "../lib/ImageShowWithFabric.svelte";
|
||||||
|
|
||||||
const RouterMap = {
|
const RouterMap = {
|
||||||
index: Main,
|
index: Main,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue