Как я могу каждый раз получать одну и ту же часть (дубликат кода) изображения из множества разных фотографий?

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

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

  • Как я могу каждый раз получать одну и ту же часть (дубликат кода) изображения из множества разных фотографий?

  • Как я могу каждый раз получать одну и ту же часть (дубликат кода) изображения из множества разных фотографий?

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

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

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

У кого-нибудь есть идея, как автоматически прочитать повторяющийся код с 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))
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
90
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

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

Спасибо за ответ CZorio! Извините за недостающую информацию. В данном исследовании мы ориентируемся только на легковые автомобили. Эти 5000 изображений имеют почти такое же расположение, как и в примере.

camiel1985 28.05.2019 19:38

Я думаю, что CNN - хороший вариант, может быть, я могу использовать для него тензорный поток. Но риск с CNN на всей фотографии заключается в том, что нейронная сеть будет пытаться найти закономерность в цифрах и буквах. Хотя, если вам нужно только применить cnn или ocr к дублирующемуся коду, я думаю, что это будет хорошая модель раньше.

camiel1985 28.05.2019 19:51
Ответ принят как подходящий

Вот подход, основанный на пакете 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 файлов! Но, конечно, это предполагает, что они правильно отформатированы и т. д. и т. д.

Спасибо за ответ Дэвид О! Звучит действительно хорошо! Я собираюсь пройти через ваше объяснение еще больше в ближайшие дни, но я обязательно попробую.

camiel1985 28.05.2019 19:55

Удачи! Я с нетерпением жду возможности увидеть, как это работает для вас. Кстати, я исправил скрытую ошибку в своем коде! 1 было изменено на sel. Обязательно используйте обновленную версию.

David O 28.05.2019 20:47

Привет, Дэвид, я был в отпуске, поэтому мне потребовалось немного времени, прежде чем попробовать. Но код хорошо работает на некоторых картинках. Но при большом количестве снимков качество картинки плохое. На некоторых картинках bwlabel не мог хорошо различать объекты, а на некоторых картинках h text mining (cat (ocr)) плохо читал рисунок.

camiel1985 02.07.2019 20:53

Спасибо, что сообщили мне, как это работает. С реальными изображениями обработка изображения перед выделением признаков, вероятно, является наиболее важным шагом. В моем примере шаг, помеченный как «зачаточный процесс изображения», следует заменить более подходящим кодом для ваших изображений. (R может работать, но может быть не лучшим для этого ...) Это должно быть адаптировано к вашим изображениям, но фильтр Собеля для улучшения краев и / или нерезкая маска для локального повышения контраста могут быть хороши для JPEGS. Удачи.

David O 03.07.2019 09:43

Другие вопросы по теме