如何每次从许多不同的照片中获取相同的图像片段(重复代码)?

How can I get the same piece (duplicate code) of an image from many different photos every time?

我想从 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))

What with the existance of multiple layouts for Dutch license plates,我不确定您是否可以硬编码一个方法来提取重复值。另外,您也没有提及您拥有的每张图像是否始终具有相同的质量 and/or orientation/scale/skew/etc.

理论上,您可以应用 Convolutional Neural Network 将车牌分为几个类别。 (0 代表 n/a,1 代表 1,2 代表 2,等等)但是我不熟悉 R 中的相关包,所以我不能给你指出一些。

这是一个基于包 EBImage 的方法。 ImageMagik 非常适合图像处理,但我认为 EBImage 可能会提供更多在这里有用的定量工具。对于所有图像处理,输入图像的质量至关重要。此处建议的方法可能会受益于噪声和伪影去除、缩放以及可能的裁剪。

此外,一些许可证似乎在感兴趣的位置有额外的符号,这些符号不是数字。显然,这种情况需要更多 pre-processing 和过滤。

示例图片

# 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"))

已生成并清理了二进制(阈值)图像以识别此处所示的对象。

# 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)

以下逻辑使用 EBImagecomputeFeatures.moment 函数识别每个对象的质心。似乎主要符号将沿着一条水平线,而候选对象将在该线上方(EBImage 图像对象中的下方 y-value)。另一种方法是查找彼此堆叠的对象,即具有相似 x-values.

的对象

对于我探索的示例,距离质心的中位数 y-value 一个标准差似乎足以识别候选对象。这用于确定如下所示的限制。当然,这个逻辑要根据实际数据来调整。

# 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")

图像显示了沿边缘丢弃对象后的分割对象。红色表示候选人,蓝色表示non-candidates.

因为有些许可证在破折号上方有两个符号,下面的代码选择最左边的可能候选对象,扩展对象蒙版和 returns 可以传递给 [=20= 的图像的矩形裁剪].

# 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 中未缩放和提取的候选图像:

另一个示例图片

应用于此示例的相同代码给出以下内容:

通过对错误和不合逻辑条件的更多检查,代码可以组装成单个函数并应用于 5000 个文件的列表!但当然,前提是它们的格式正确,等等。