1、需要
要用 JS 来实现魔法棒的性能,首先须要实现找到邻近色彩的像素点,再标识进去。
刚实现了找到了邻近根本的像素点的局部。
2、代码
是图像宰割中的泛洪算法在前端中的利用。
<!--
* @Author: ArdenZhao
* @Date: 2022-01-18 14:09:54
* @LastEditors: Do not edit
* @LastEditTime: 2022-02-08 19:02:01
* @FilePath: /magic_wand/demo/4、myFloodFillData.html
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello OpenCV.js</title>
<style>
#imageSrc,
#canvasOutput {
width: 50%;
height: auto;
}
</style>
</head>
<body>
<h2>Hello OpenCV.js</h2>
<p id="status">OpenCV.js is loading...</p>
<div>
<div class="inputoutput">
<img id="imageSrc" alt="No Image" />
<div class="caption">imageSrc</div>
</div>
<div class="inputoutput">
<canvas id="canvasOutput"></canvas>
<div class="caption">canvasOutput</div>
</div>
</div>
<script type="text/javascript">
// 获取图片标签
let imgElement = document.getElementById('imageSrc');
// 获取 canvas 标签
let canvasElement = document.getElementById('canvasOutput');
imgElement.src = 'https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF';
imgElement.crossOrigin = "Anonymous";
function init_image(self, image_file) {self.image = cv2.imdecode(np.fromfile(image_file, dtype = np.uint8), 1)
self.image_raw = self.image.copy()
// self.img_h, self.img_w = self.image.shape[0: 2] // 原图宽高
}
let imageArr = [];
// 2、获取图片的宽高
let imageWidth = 0
let imageHeight = 0
imgElement.onload = function () {
imageWidth = imgElement.width
imageHeight = imgElement.height
};
// 异步获取后显示失常
function onOpenCvReady() {console.log('[ cv] >', cv)
document.getElementById('status').innerHTML = 'OpenCV.js is ready.';
cv['onRuntimeInitialized'] = () => {
// 1、获取图片的数据
let mat = cv.imread(imgElement);
let arr = []
// 3、构建图片的二维数组
for (let i = 0; i < mat.data.length; i = i + 4) {arr.push(mat.data.slice(i, i + 4));
}
for (let j = 0; j < arr.length; j = j + imageWidth) {imageArr.push(arr.slice(j, j + imageWidth));
}
cv.imshow('canvasOutput', mat);
mat.delete(); // 避免内存透露};
}
// 4、获取到 Canvas 点击的坐标
canvasElement.addEventListener('click', (e) => {let clickPoint = getMousePos(canvasElement, e)
let seedMark = myFloodFill(imageArr, 10, clickPoint) // 默认 20-30 左右,动静输出
}, false);
function getMousePos(canvas, event) {var rect = canvas.getBoundingClientRect();// 办法返回元素的大小及其绝对于视口的地位
var x = event.clientX - rect.left * (canvas.width / rect.width);
var y = event.clientY - rect.top * (canvas.height / rect.height);
return [Math.round(x), Math.round(y)];
}
// 5、改写泛洪办法,取得返回的区域
function myFloodFill(image, thresh, seedpoint) {
// 构建图片的二维数组
let seedMark = new Array(imageHeight).fill(0).map(() => new Array(imageWidth).fill(0));
// 四邻域
let p = 4
let connection = [[-1, 0], [0, 1], [1, 0], [0, -1]]
let seeds = [[seedpoint[1], seedpoint[0]]] // 竖直方向在前,程度方向在后
let interval = thresh
while (seeds.length > 0) {
// 栈顶元素出栈
// pt=(y,x),opencv 中程度为 x 坐标,竖直为 y 坐标,seeds 输出坐标为先竖直坐标,后程度坐标
let pt = seeds.shift(0)
let Ra = image[pt[0]][pt[1]][0]
let Ga = image[pt[0]][pt[1]][1]
let Ba = image[pt[0]][pt[1]][2]
for (let i = 0; i < p; i++) {let x = pt[1] + connection[i][0]
let y = pt[0] + connection[i][1]
// 检测边界点
if (x < 0 || x >= imageWidth || y < 0 || y >= imageHeight) {continue}
let Rb = image[y][x][0]
let Gb = image[y][x][1]
let Bb = image[y][x][2]
// 满足魔法点的条件
if (seedMark[y][x] == 0 && ((Ra - Rb) <= interval) && (Ga - Gb) <= interval && (Ba - Bb) <= interval) {
// 将魔法点标记为已拜访
seedMark[y][x] = 1
// 将魔法点压入栈
seeds.push([y, x])
}
}
}
return seedMark
}
// todo
// 6、显示图像的遮层
</script>
<script async src="https://docs.opencv.org/4.5.0/opencv.js" onload="onOpenCvReady();" type="text/javascript"></script>
</body>
</html>