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>
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { onMount, onDestroy } from "svelte";
|
||||
|
||||
import Navbar from "./Navbar.svelte";
|
||||
import Mask from "./Mask.svelte";
|
||||
import { ImageProcess } from "./utils";
|
||||
|
||||
const cv = window.cv;
|
||||
let image_process = new ImageProcess();
|
||||
|
||||
export let url = "test.jpg";
|
||||
|
||||
let canvas_dom;
|
||||
let canvas;
|
||||
let resize_tag;
|
||||
let image;
|
||||
|
||||
let image_for_show;
|
||||
let window_width;
|
||||
let window_height;
|
||||
let canvas_width = 0;
|
||||
let canvas_height = 0;
|
||||
let active;
|
||||
|
||||
let mask_tag = false;
|
||||
|
||||
function LabelItem(label, items) {
|
||||
this.label = label;
|
||||
|
|
@ -26,7 +31,6 @@
|
|||
}
|
||||
|
||||
function OperationItem(name, icon, handler = null) {
|
||||
this.id = uuidv4();
|
||||
this.name = name;
|
||||
this.icon = icon;
|
||||
this.handler = handler;
|
||||
|
|
@ -38,12 +42,42 @@
|
|||
["重新采集", "mdi mdi-reply-outline"],
|
||||
]),
|
||||
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-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("文件操作", [
|
||||
["保存到本地", "mdi mdi-content-save-outline"],
|
||||
|
|
@ -57,108 +91,153 @@
|
|||
}
|
||||
|
||||
function on_window_resize() {
|
||||
/*setTimeout(() => {
|
||||
let scale = Math.min(
|
||||
canvas_height / image.height,
|
||||
canvas_width / image.width
|
||||
if (resize_tag) {
|
||||
clearTimeout(resize_tag);
|
||||
}
|
||||
resize_tag = setTimeout(function () {
|
||||
image_process.roi_init();
|
||||
if (image) {
|
||||
let pre_scale = Math.min(
|
||||
canvas_height / image.rows,
|
||||
canvas_width / image.cols
|
||||
);
|
||||
let pre_dsize = new cv.Size(
|
||||
pre_scale * image.cols,
|
||||
pre_scale * image.rows
|
||||
);
|
||||
cv.resize(
|
||||
image_for_show,
|
||||
image_for_show,
|
||||
pre_dsize,
|
||||
0,
|
||||
0,
|
||||
cv.INTER_AREA
|
||||
);
|
||||
|
||||
canvas.setWidth(image.width * scale);
|
||||
canvas.setHeight(image.height * scale);
|
||||
|
||||
image.scale(scale);
|
||||
}, 50);*/
|
||||
show_image();
|
||||
}
|
||||
}, 40);
|
||||
}
|
||||
|
||||
function rotate(img, angle) {
|
||||
function show_image() {
|
||||
mask_tag = false;
|
||||
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;
|
||||
console.time("image show");
|
||||
if (image_process.roi_tag) {
|
||||
dst = image_for_show.roi(image_process.ROI_rect);
|
||||
} else {
|
||||
dst = image_for_show.clone();
|
||||
}
|
||||
|
||||
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")) {
|
||||
}
|
||||
|
||||
let dst = img.clone();
|
||||
for (const [key, value] of Object.entries(option)) {
|
||||
if (key === "resize") {
|
||||
let scale = Math.min(
|
||||
canvas_height / image.height,
|
||||
canvas_width / image.width
|
||||
);
|
||||
dst = resize(dst, scale);
|
||||
console.log(dst);
|
||||
}
|
||||
if (key === "rotate") {
|
||||
dst = rotate
|
||||
}
|
||||
}
|
||||
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);
|
||||
dst.delete;
|
||||
|
||||
console.timeEnd("image show");
|
||||
dst.delete();
|
||||
}
|
||||
|
||||
async function init_canvas() {
|
||||
let img = new Image();
|
||||
image_for_show = new cv.Mat();
|
||||
img.src = url;
|
||||
img.onload = function () {
|
||||
setTimeout(() => {
|
||||
image = cv.imread(img);
|
||||
let scale = Math.min(
|
||||
let pre_scale = Math.min(
|
||||
canvas_height / image.rows,
|
||||
canvas_width / image.cols
|
||||
);
|
||||
let dst = new cv.Mat();
|
||||
let dsize = new cv.Size(scale * image.cols, scale * image.rows);
|
||||
|
||||
cv.resize(image, dst, dsize, 0, 0, cv.INTER_AREA);
|
||||
cv.imshow("canvas", dst);
|
||||
/* image = new fabric.Image(img);
|
||||
let scale = Math.min(
|
||||
canvas_height / image.height,
|
||||
canvas_width / image.width
|
||||
let pre_dsize = new cv.Size(
|
||||
pre_scale * image.cols,
|
||||
pre_scale * image.rows
|
||||
);
|
||||
cv.resize(image, image_for_show, pre_dsize, 0, 0, cv.INTER_AREA);
|
||||
|
||||
image.scale(scale);
|
||||
canvas.setWidth(image.width * scale);
|
||||
canvas.setHeight(image.height * scale);
|
||||
canvas.add(image);
|
||||
console.log(image);*/
|
||||
show_image();
|
||||
}, 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 () => {
|
||||
canvas_height = window_height - 64;
|
||||
canvas_width = (window_width * 13) / 16;
|
||||
init_canvas();
|
||||
console.log(window);
|
||||
});
|
||||
|
||||
onDestroy(async () => {
|
||||
if (image.delete) {
|
||||
image.delete();
|
||||
}
|
||||
if (image_for_show.delete) {
|
||||
image_for_show.delete();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
@ -166,6 +245,7 @@
|
|||
bind:innerHeight={window_height}
|
||||
bind:innerWidth={window_width}
|
||||
on:resize={on_window_resize}
|
||||
on:keydown={keyboard_move_roi}
|
||||
/>
|
||||
|
||||
<div class="disable-selection">
|
||||
|
|
@ -181,9 +261,7 @@
|
|||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<li>
|
||||
<a
|
||||
class:is-active={active === item.id}
|
||||
on:click={() => {
|
||||
active = item.id;
|
||||
if (item.handler) {
|
||||
item.handler();
|
||||
}
|
||||
|
|
@ -201,7 +279,16 @@
|
|||
</aside>
|
||||
</div>
|
||||
<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>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,12 @@
|
|||
<script>
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
import { fabric } from "fabric";
|
||||
|
||||
import Navbar from "./Navbar.svelte";
|
||||
import { ImageProcessing } from "./utils";
|
||||
|
||||
export let url = "test.jpg";
|
||||
|
||||
let img_process = new ImageProcessing();
|
||||
|
||||
let canvas_dom;
|
||||
let canvas;
|
||||
let image;
|
||||
|
|
@ -18,7 +14,7 @@
|
|||
let window_height;
|
||||
let canvas_width = 0;
|
||||
let canvas_height = 0;
|
||||
let active;
|
||||
let resize_tag;
|
||||
|
||||
function LabelItem(label, items) {
|
||||
this.label = label;
|
||||
|
|
@ -29,7 +25,6 @@
|
|||
}
|
||||
|
||||
function OperationItem(name, icon, handler = null) {
|
||||
this.id = uuidv4();
|
||||
this.name = name;
|
||||
this.icon = icon;
|
||||
this.handler = handler;
|
||||
|
|
@ -39,20 +34,34 @@
|
|||
new LabelItem("采集操作", [
|
||||
["确认并返回", "mdi mdi-checkbox-marked-circle-outline"],
|
||||
["重新采集", "mdi mdi-reply-outline"],
|
||||
["取消", "mdi mdi-alpha-x-circle-outline"],
|
||||
]),
|
||||
new LabelItem("图像操作", [
|
||||
[
|
||||
"向左旋转",
|
||||
"mdi mdi-file-rotate-left-outline",
|
||||
() => {
|
||||
console.log("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-crop"],
|
||||
["滚轮缩放", "mdi mdi-loupe"],
|
||||
[
|
||||
"还原",
|
||||
"mdi mdi-alpha-x-circle-outline",
|
||||
() => {
|
||||
init_canvas();
|
||||
},
|
||||
],
|
||||
]),
|
||||
new LabelItem("文件操作", [
|
||||
["保存到本地", "mdi mdi-content-save-outline"],
|
||||
|
|
@ -66,7 +75,10 @@
|
|||
}
|
||||
|
||||
function resize() {
|
||||
setTimeout(() => {
|
||||
if (resize_tag) {
|
||||
clearTimeout(resize_tag);
|
||||
}
|
||||
resize_tag = setTimeout(() => {
|
||||
let scale = Math.min(
|
||||
canvas_height / image.height,
|
||||
canvas_width / image.width
|
||||
|
|
@ -74,7 +86,7 @@
|
|||
|
||||
canvas.setWidth(image.width * scale);
|
||||
canvas.setHeight(image.height * scale);
|
||||
|
||||
image.rotate(90);
|
||||
image.scale(scale);
|
||||
}, 50);
|
||||
}
|
||||
|
|
@ -85,7 +97,6 @@
|
|||
img.onload = async function () {
|
||||
setTimeout(() => {
|
||||
canvas = new fabric.StaticCanvas(canvas_dom);
|
||||
setTimeout(() => {
|
||||
image = new fabric.Image(img);
|
||||
let scale = Math.min(
|
||||
canvas_height / image.height,
|
||||
|
|
@ -96,9 +107,7 @@
|
|||
canvas.setWidth(image.width * scale);
|
||||
canvas.setHeight(image.height * scale);
|
||||
canvas.add(image);
|
||||
console.log(image);
|
||||
}, 50);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -106,7 +115,6 @@
|
|||
canvas_height = window_height - 64;
|
||||
canvas_width = (window_width * 13) / 16;
|
||||
init_canvas();
|
||||
console.log(window)
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
@ -129,9 +137,7 @@
|
|||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<li>
|
||||
<a
|
||||
class:is-active={active === item.id}
|
||||
on:click={() => {
|
||||
active = item.id;
|
||||
if (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>
|
||||
181
src/lib/utils.js
181
src/lib/utils.js
|
|
@ -1,5 +1,8 @@
|
|||
import procedure from "../assets/Procedure.json";
|
||||
|
||||
const cv = window.cv;
|
||||
const move_step = 3;
|
||||
|
||||
export function Operation(step) {
|
||||
this.step = step;
|
||||
|
||||
|
|
@ -18,7 +21,6 @@ export function Operation(step) {
|
|||
if (!s) {
|
||||
return procedure.find((e) => e.id === this.step).name;
|
||||
}
|
||||
console.log(s);
|
||||
return procedure.find((e) => e.id === s).name;
|
||||
};
|
||||
|
||||
|
|
@ -26,3 +28,180 @@ export function Operation(step) {
|
|||
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 Login from "../lib/Login.svelte";
|
||||
import Image from "../lib/ImageShow.svelte";
|
||||
// import Image from "../lib/ImageShowWithFabric.svelte";
|
||||
|
||||
const RouterMap = {
|
||||
index: Main,
|
||||
|
|
|
|||
Loading…
Reference in New Issue