首页 > 解决方案 > 如何每次从许多不同的照片中获取相同的图像(重复代码)?

问题描述

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

标签: rimageimage-processingimage-recognition

解决方案


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

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

示例图像

样品 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"))

已生成并清理二进制(阈值)图像以识别对象,如下所示。

预处理和阈值图像

# 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。似乎主要符号将沿着一条水平线,而候选对象将在该线上方(EBImage图像对象中的较低 y 值)。另一种方法是查找彼此堆叠的对象,即具有相似 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")

该图像显示了沿边缘丢弃对象后的分割对象。红色代表候选人,蓝色代表非候选人。

加价候选人

由于某些许可证在破折号上方有两个符号,因此以下代码选择最左边的可能候选者,扩展对象掩码并返回可以传递给的图像的矩形裁剪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 中未缩放和提取的候选图像: 答案 1

另一个示例图像

样品 2

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

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


推荐阅读