Как я могу получить один и тот же фрагмент (дублирующий код) изображения из разных фотографий каждый раз? - PullRequest
1 голос
/ 27 мая 2019

Из 5000 фотографий номерных знаков я хочу определить, какой дубликат кода у этих номерных знаков.

Вот 2 примера дубликата кода на номерном знаке.

В первом примере дублирующийся код равен 2, а во втором примере дублирующийся код равен 1.

С пакетом Magick и Tesseract, см. Код ниже, я смог получить фрагмент фотографии из первого примера, где есть дубликат кода, и прочитать его. Только во втором примере и на других фотографиях фото отличается.

Так что я ищу что-то, что может распознать, где находится повторяющийся код, и прочитать его. Примечание: дубликат кода всегда выше 1-го знака отступа.

У кого-нибудь есть идеи, как автоматически прочитать дублирующийся код с 5000 разных фотографий?

library(magick)
library(tesseract)

#Load foto:
foto <- image_read("C:/Users/camie/OneDrive/Documenten/kenteken3.jpg")

 #Get piece of photo where duplicate code is retrieved:
foto2 <- image_crop(foto,"10X24-620-170")

#read duplicate code:
cat(ocr(foto3))

Ответы [ 2 ]

1 голос
/ 28 мая 2019

Вот подход, основанный на пакете EBImage. ImageMagik отлично подходит для манипулирования изображениями, но я думаю, что EBImage может предоставить больше количественных инструментов, которые здесь полезны. Что касается всей обработки изображений, качество входного изображения имеет большое значение. Предложенный здесь подход, вероятно, выиграет от удаления шума и артефактов, масштабирования и, возможно, обрезки.

Кроме того, некоторые лицензии имеют дополнительные символы в интересующей позиции, которые не являются числами. Очевидно, что для таких случаев требуется больше предварительной обработки и фильтрации.

Образец изображения

sample 1

# Starting from EBImage
  if (!require(EBImage)) {
    source("http://bioconductor.org/biocLite.R")
    biocLite("EBImage")
    library(EBImage)
  }

# Test images
#   setwd(<image directory>)
    f1 <- "license1.jpg"
    f2 <- "license2.jpg"

# Read image and convert to normalized greyscale
  img0 <- readImage(f1)
  img <- channel(img0, "grey")
  img <- normalize(img)
# plot(img) # insert plot or display commands as desired

# Rudimentary image process for ~300 pixel wide JPEG
  xmf <- medianFilter(img, 1)
  xgb <- gblur(xmf, 1)
  xth <- xgb < otsu(xgb) # Otsu's algorithm to determine best threshold
  xto <- opening(xth, makeBrush(3, shape = "diamond"))

Было создано и очищено двоичное (пороговое) изображение для идентификации объектов, как показано здесь.

preprocessed and thresholded image

# Create object mask with unique integer for each object
  xm <- bwlabel(xto)
# plot(colorLabels(xm)) # optional code to visualize the objects

В дополнение к элементарной обработке изображения может быть применена некоторая «обработка объекта», как показано здесь. Объекты вдоль края не будут представлять интереса, поэтому они будут удалены. Точно так же артефакты, которые вызывают горизонтальные (широкие) полосы, также могут быть удалены.

# Drop objects touching the edge
  nx <- dim(xm)[1]
  ny <- dim(xm)[2]
  sel <- unique(c(xm[1,], xm[nx,], xm[,1], xm[,ny]))
  sel <- sel[sel != 0]
  xm <- rmObjects(xm, sel, reenumerate = TRUE)

# Drop exceptionally wide objects (33% of image width) 
  major <- computeFeatures.moment(xm)[,"m.majoraxis"]
  sel <- which(major > nx/3)
  xm <- rmObjects(xm, sel, reenumerate = TRUE)

Следующая логика идентифицирует центр масс для каждого объекта с функцией computeFeatures.moment, равной EBImage. Кажется, что основные символы будут расположены вдоль горизонтальной линии, а объект-кандидат будет выше этой линии (меньшее значение y в EBImage объекте Image). Альтернативный подход состоит в том, чтобы находить объекты, наложенные друг на друга, то есть объекты с одинаковыми значениями x.

Для примеров, которые я исследовал, одного стандартного отклонения от медианного значения y для центра масс, по-видимому, достаточно для идентификации объекта-кандидата. Это используется для определения пределов, показанных ниже. Конечно, эта логика должна быть скорректирована в соответствии с фактическими данными.

# Determine center of mass for remaining objects
  M <- computeFeatures.moment(xm)
  x <- M[,1]
  y <- M[,2]

# Show suggested limit on image (y coordinates are inverted)
  plot(img)
  limit <- median(y) - sd(y)
  abline(h = limit, col = "red")

# Show centers of mass on original image
  ok <- y < limit
  points(x[!ok], y[!ok], pch = 16, col = "blue")
  points(x[ok], y[ok], pch = 16, col = "red")

На рисунке показаны сегментированные объекты после отбрасывания объектов по краю. Красным цветом показаны кандидаты, синим - кандидаты.

candidates with mark-up

Поскольку некоторые лицензии имеют два символа над тире, следующий код выбирает крайнего левого из возможных кандидатов, расширяет маску объекта и возвращает прямоугольный фрагмент изображения, который можно передать в ocr().

# Accept leftmost (first) of candidate objects
  left <- min(x[which(ok)])
  sel <- which(x == left)

# Enlarge object mask and extract the candidate image
  xm <- dilate(xm, makeBrush(7, "disc"))
  ix <- range(apply(xm, 2, function(v) which(v == sel)))
  iy <- range(apply(xm, 1, function(v) which(v == sel)))
  xx <- ix[1]:ix[2]
  yy <- iy[1]:iy[2]

# "Return" selected portion of image
  ans <- img[xx, yy] # this is what can be passed to tesseract
  plot(ans, interpolate = FALSE)

Вот немасштабированное и извлеченное изображение кандидата из примера 1: answer 1

Еще один пример изображения

sample 2

Тот же код, примененный к этому примеру, дает следующее: answer 2

С помощью еще нескольких проверок на наличие ошибок и нелогичных условий код можно собрать в одну функцию и применить к списку из 5000 файлов! Но, конечно, это предполагает, что они правильно отформатированы и т. Д. И т. Д.

1 голос
/ 28 мая 2019

Что с существованием нескольких макетов для голландских номерных знаков , я не уверен, что вы просто можете жестко закодировать метод для извлечения значения дублирования.Кроме того, вы не упоминаете, если каждое ваше изображение всегда имеет одинаковое качество и / или ориентацию / масштаб / наклон / и т. Д.

Теоретически можно применить Сверточную нейронную сеть , которая классифицируетномерные знаки в нескольких категориях.(0 для н / д, 1 для 1, 2 для 2 и т. Д.) Однако я не знаком со связанными пакетами в R, поэтому я не смогу указать вам некоторые из них.

...