#java #алгоритм #opencv
У меня есть проект по распознаванию чисел. Я хочу выделить каждую цифру, но есть близко находящиеся числа, которые я хочу разделить. Как можно разделить такие числа?
Ответы
Ответ 1
В данном случае должна помочь морфологическая операция opening - комбинация эрозии и дилатации. Первый этап удалит отдельные точки и тонкие мостики, второй восстановит общие очертания в несколько сглаженном виде без этих деталей. Конечно, при этом какие-то фигуры могут рассыпаться на части (например, из за дефектов в правой пятёрке). Нужно смотреть, поможет ли предварительный closing для уничтожения дефектов, или приведёт к неубиваемым мостикам-спайкам. Вообще для таких изображений анализируют объекты и строят решётку - цифры же определённого размера и положение их не случайно, в таком случае разделение производится по границам ячеек/ограничивающих прямоугольников.Ответ 2
Я не знаю как называется этот способ, он основан на построении гистограммы изображения, и поиске локальных минимумов, но сначала нужно найти и залить все замкнутые области. let img = new Image(); img.crossOrigin = 'anonymous'; img.src = 'https://i.imgur.com/EqAIRNx.png'; let srcCtx = src.getContext('2d'), gistCtx = gist.getContext('2d'); img.onload = function() { src.width = gist.width = img.width; src.height = gist.height = img.height; srcCtx.drawImage(img, 0, 0); let imgData = srcCtx.getImageData(0, 0, img.width, img.height) let gistData = Array(img.width).fill(0); for(var x = 0; x10 ? 1 : 0; gistData.forEach((e,i) => line(gistCtx, i, e)) gistCtx.strokeStyle = srcCtx.strokeStyle = 'red'; extrem(gistData, 12).min .map(e => Math.floor(e[0]/2 + e[1]/2)) .forEach((e, i) => { line(gistCtx, e, img.height) line(srcCtx, e, img.height) }) } function line(ctx, x, h) { ctx.beginPath(); ctx.moveTo(x, img.height); ctx.lineTo(x, img.height - h); ctx.stroke(); } function extrem(y, eps) { let s,M,m,j, i=0, min=[], max=[], greater = a => a >= M - eps, lesser = a => a <= m + eps; for (; i < y.length; i++) { if (s && M - eps <= y[i]) M = Math.max(M, y[i]) else if (!s && m + eps >= y[i]) m = Math.min(m, y[i]) else if (s) m = iter(max, greater) else M = iter(min, lesser) } return {min, max}; function iter(arr, cond) { j = i - 1; while (cond(y[j])) j--; arr.push([j, i]); s = !s; return y[i]; } } PS: похоже что при помощи нахождения минимумов построчно и вращении исходного изображения можно еще найти на сколько нужно повернуть картинку, чтобы текст встал четко по горизонтали.