Görüntülerde bulunan tüm alfasayısal metni tanımlamak için YOLO veya diğer görüntü tanıma tekniklerini kullanma


12

Hepsi metin etiketi yerine alfasayısal karakterler olarak etiketler içeren birden çok görüntü diyagramı var. YOLO modelimin, içinde bulunan tüm sayıları ve alfasayısal karakterleri tanımlamasını istiyorum.

Aynı şeyi yapmak için YOLO modelimi nasıl eğitebilirim. Veri kümesini burada bulabilirsiniz. https://drive.google.com/open?id=1iEkGcreFaBIJqUdAADDXJbUrSj99bvoi

Örneğin: sınırlayıcı kutulara bakın. YOLO'nun metnin nerede olduğunu tespit etmesini istiyorum. Ancak şu anda içindeki metni tanımlamak gerekli değildir.

resim açıklamasını buraya girin

Ayrıca bu tür görüntüler için de aynı şeylerin yapılması gerekir resim açıklamasını buraya girin resim açıklamasını buraya girin

Görüntüleri indirilebilir burada

Bu opencv kullanarak denedim ama veri kümesindeki tüm görüntüler için çalışmaz.

import cv2
import numpy as np
import pytesseract

pytesseract.pytesseract.tesseract_cmd = r"C:\Users\HPO2KOR\AppData\Local\Tesseract-OCR\tesseract.exe"

image = cv2.imread(r'C:\Users\HPO2KOR\Desktop\Work\venv\Patent\PARTICULATE DETECTOR\PD4.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
clean = thresh.copy()

horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15,1))
detect_horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
cnts = cv2.findContours(detect_horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(clean, [c], -1, 0, 3)

vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,30))
detect_vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
cnts = cv2.findContours(detect_vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(clean, [c], -1, 0, 3)

cnts = cv2.findContours(clean, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    if area < 100:
        cv2.drawContours(clean, [c], -1, 0, 3)
    elif area > 1000:
        cv2.drawContours(clean, [c], -1, 0, -1)
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)
    x,y,w,h = cv2.boundingRect(c)
    if len(approx) == 4:
        cv2.rectangle(clean, (x, y), (x + w, y + h), 0, -1)

open_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2,2))
opening = cv2.morphologyEx(clean, cv2.MORPH_OPEN, open_kernel, iterations=2)
close_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,2))
close = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, close_kernel, iterations=4)
cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    area = cv2.contourArea(c)
    if area > 500:
        ROI = image[y:y+h, x:x+w]
        ROI = cv2.GaussianBlur(ROI, (3,3), 0)
        data = pytesseract.image_to_string(ROI, lang='eng',config='--psm 6')
        if data.isalnum():
            cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 2)
            print(data)

cv2.imwrite('image.png', image)
cv2.imwrite('clean.png', clean)
cv2.imwrite('close.png', close)
cv2.imwrite('opening.png', opening)
cv2.waitKey()

Benim için aynısını yapabilen herhangi bir model veya herhangi bir opencv tekniği veya önceden eğitilmiş bir model var mı? Görüntülerde bulunan tüm alfasayısal karakterlerin etrafındaki sınırlayıcı kutulara ihtiyacım var. Bundan sonra içinde ne olduğunu tanımlamam gerekiyor. Ancak ikinci kısım şu anda önemli değil.




görüntüler için çalışmayan
Pulkit Bhatnagar

Yanıtlar:


7

Olası bir yaklaşım, Zhou ve arkadaşlarının 2017 tarihli EAST: Verimli ve Doğru Sahne Metni Dedektörü'ne dayanan EAST (Verimli ve Doğru Sahne Metni) derin öğrenme metin dedektörünü kullanmaktır . Model başlangıçta doğal sahne görüntülerindeki metni tespit etmek için eğitildi, ancak şema görüntülerine uygulamak mümkün olabilir. EAST oldukça sağlamdır ve bulanık veya yansıtıcı metinleri algılayabilir. İşte Adrian Rosebrock'un EAST uygulamasının değiştirilmiş bir versiyonu. Metin algılayıcıyı doğrudan görüntüye uygulamak yerine, metin algılama gerçekleştirmeden önce görüntüdeki metin olmayan nesneleri kaldırmayı deneyebiliriz. Fikir algılama uygulamadan önce yatay çizgileri, dikey çizgileri ve metin olmayan konturları (eğriler, köşegenler, dairesel şekiller) kaldırmaktır. İşte resimlerinizden bazılarının sonuçları:

->Yeşil renkten kaldırmak için Metin olmayan konturlar girin

Sonuç

Diğer Resimler

frozen_east_text_detection.pbMetin algılamayı gerçekleştirmek için gerekli olan önceden hazırlanmış modeli burada bulabilirsiniz . Model metnin çoğunu yakalasa da, sonuçlar% 100 doğru değildir ve muhtemelen doğal sahne görüntüleri üzerinde nasıl eğitildiğinden dolayı yanlış pozitiflere sahiptir. Daha doğru sonuçlar elde etmek için muhtemelen kendi özel modelinizi eğitmeniz gerekir. Ancak, kutudan çıktığı gibi iyi bir çözüm istiyorsanız, bu size yardımcı olacaktır. EAST metin dedektörünün daha kapsamlı bir açıklaması için Adrian'ın OpenCV Metin Algılama (EAST metin dedektörü) blog gönderisine göz atın .

kod

from imutils.object_detection import non_max_suppression
import numpy as np
import cv2

def EAST_text_detector(original, image, confidence=0.25):
    # Set the new width and height and determine the changed ratio
    (h, W) = image.shape[:2]
    (newW, newH) = (640, 640)
    rW = W / float(newW)
    rH = h / float(newH)

    # Resize the image and grab the new image dimensions
    image = cv2.resize(image, (newW, newH))
    (h, W) = image.shape[:2]

    # Define the two output layer names for the EAST detector model that
    # we are interested -- the first is the output probabilities and the
    # second can be used to derive the bounding box coordinates of text
    layerNames = [
        "feature_fusion/Conv_7/Sigmoid",
        "feature_fusion/concat_3"]

    net = cv2.dnn.readNet('frozen_east_text_detection.pb')

    # Construct a blob from the image and then perform a forward pass of
    # the model to obtain the two output layer sets
    blob = cv2.dnn.blobFromImage(image, 1.0, (W, h), (123.68, 116.78, 103.94), swapRB=True, crop=False)
    net.setInput(blob)
    (scores, geometry) = net.forward(layerNames)

    # Grab the number of rows and columns from the scores volume, then
    # initialize our set of bounding box rectangles and corresponding
    # confidence scores
    (numRows, numCols) = scores.shape[2:4]
    rects = []
    confidences = []

    # Loop over the number of rows
    for y in range(0, numRows):
        # Extract the scores (probabilities), followed by the geometrical
        # data used to derive potential bounding box coordinates that
        # surround text
        scoresData = scores[0, 0, y]
        xData0 = geometry[0, 0, y]
        xData1 = geometry[0, 1, y]
        xData2 = geometry[0, 2, y]
        xData3 = geometry[0, 3, y]
        anglesData = geometry[0, 4, y]

        # Loop over the number of columns
        for x in range(0, numCols):
            # If our score does not have sufficient probability, ignore it
            if scoresData[x] < confidence:
                continue

            # Compute the offset factor as our resulting feature maps will
            # be 4x smaller than the input image
            (offsetX, offsetY) = (x * 4.0, y * 4.0)

            # Extract the rotation angle for the prediction and then
            # compute the sin and cosine
            angle = anglesData[x]
            cos = np.cos(angle)
            sin = np.sin(angle)

            # Use the geometry volume to derive the width and height of
            # the bounding box
            h = xData0[x] + xData2[x]
            w = xData1[x] + xData3[x]

            # Compute both the starting and ending (x, y)-coordinates for
            # the text prediction bounding box
            endX = int(offsetX + (cos * xData1[x]) + (sin * xData2[x]))
            endY = int(offsetY - (sin * xData1[x]) + (cos * xData2[x]))
            startX = int(endX - w)
            startY = int(endY - h)

            # Add the bounding box coordinates and probability score to
            # our respective lists
            rects.append((startX, startY, endX, endY))
            confidences.append(scoresData[x])

    # Apply non-maxima suppression to suppress weak, overlapping bounding
    # boxes
    boxes = non_max_suppression(np.array(rects), probs=confidences)

    # Loop over the bounding boxes
    for (startX, startY, endX, endY) in boxes:
        # Scale the bounding box coordinates based on the respective
        # ratios
        startX = int(startX * rW)
        startY = int(startY * rH)
        endX = int(endX * rW)
        endY = int(endY * rH)

        # Draw the bounding box on the image
        cv2.rectangle(original, (startX, startY), (endX, endY), (36, 255, 12), 2)
    return original

# Convert to grayscale and Otsu's threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
clean = thresh.copy()

# Remove horizontal lines
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15,1))
detect_horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
cnts = cv2.findContours(detect_horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(clean, [c], -1, 0, 3)

# Remove vertical lines
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,30))
detect_vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
cnts = cv2.findContours(detect_vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(clean, [c], -1, 0, 3)

# Remove non-text contours (curves, diagonals, circlar shapes)
cnts = cv2.findContours(clean, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    if area > 1500:
        cv2.drawContours(clean, [c], -1, 0, -1)
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)
    x,y,w,h = cv2.boundingRect(c)
    if len(approx) == 4:
        cv2.rectangle(clean, (x, y), (x + w, y + h), 0, -1)

# Bitwise-and with original image to remove contours
filtered = cv2.bitwise_and(image, image, mask=clean)
filtered[clean==0] = (255,255,255)

# Perform EAST text detection
result = EAST_text_detector(image, filtered)

cv2.imshow('filtered', filtered)
cv2.imshow('result', result)
cv2.waitKey()

Çok eksiksiz bir cevap. Kaç saat çaba?
karlphillip

Yaklaşık bir saat ve yazmak için 30 dakika daha
nathancy

Bugüne kadar, birkaç gün içinde son derece benzer CV sorularıyla ortaya çıkan insanların sayısını hala şaşırttım. Neredeyse aynı görüntü işleme sınıfından adamlar ödevlerini bitirmek için yardım arıyor ya da sadece onlar için ödev yapacak birini arıyorlar. Gerçekten tuhaf bir "tesadüf".
karlphillip

2
@karlphillip Belki bu soru tanıdık geliyor, çünkü OP yaklaşık bir hafta önce yayınladı. Hemen hemen tüm davalarını kutudan çıkardığı bir CTRL + C, CTRL + V cevabı istiyor, bu yüzden sanırım bu aynı soruyu birkaç hafta içinde tekrar görebilirsiniz!
eldesgraciado

3
@eldesgraciado OP'nin birkaç hafta önce benzer bir soru gönderdiğini fark ettim . Şimdiye kadar aynı kişi olduğunu bile fark etmedim! Ayrıca sorunun neden çok tanıdık
geldiğini

6

Kolaylık olması için keras_ocr paketini eklemek istiyorum . Pip ile kolayca kurulabilir ve yanılmıyorsam EAST dedektöründen biraz daha yeni olan CRAFT metin dedektörüne dayanır.

Tespitin yanında zaten OCR de var! Sonuçlar aşağıda görüldüğü gibidir, bunu kabul edilen cevaptan alternatif, belki de daha kolay bir uygulama olarak görün.resim açıklamasını buraya girin


Merhaba victor, resimlerimin en az% 70'inde çalışıyor mu?
Pulkit Bhatnagar

Veri kümenize etiket eklemediniz. Dolayısıyla, bir etiketle karşılaştırarak çalışıp çalışmadığını doğrulamanın bir yolu yoksa, resimlerin% ne kadarının üzerinde çalıştığını gerçekten söyleyemem. Ancak, bu bir pip paketi, bu yüzden veri
kümenizde

4

Açıkladığınız şey OCR ( Optik karakter tanıma ) gibi görünüyor. IBM ve diğerlerinden bir tane olsa da, bildiğim bir OCR motoru tesseract .

YOLO başlangıçta çok farklı bir görev için eğitildiğinden, metni yerelleştirmek için kullanmak büyük olasılıkla onu sıfırdan yeniden eğitmeyi gerektirecektir. Bir kimse mevcut gerçekleri (özel ayarınıza uyarlanmış) zemin gerçekliği için kullanmaya çalışabilir (her ne kadar modelin genellikle en fazla zemin gerçekliği kadar iyi olacağını hatırlamakta fayda var). Ya da, belki de daha kolay bir şekilde, eğitim için sentetik veriler oluşturun (yani, mevcut çizimlere seçtiğiniz konumlara metin ekleyin ve ardından yerelleştirmek için eğitin).

Alternatif olarak, tüm hedef görüntüleriniz yukarıdakine benzer bir şekilde yapılandırılmışsa, sembolleri ayırmak / segmentlere ayırmak için yukarıda yaptığınız gibi klasik CV buluşsal yöntemlerini kullanarak zemin gerçeği oluşturmaya çalışabilir, ardından MNIST veya benzeri bir eğitim için bir CNN kullanılarak sınıflandırma verilen bir damla sembol içeriyorsa.

Birlikte biraz tecrübe vardı mesela, piton mevcut uygulamalar vardır - durum için size YOLO için opt yapmak bu bir - kendi zemin gerçeği ile eğitim kurmak oldukça basit olmalıdır.

Son olarak, YOLO veya CNN kullanmak kendi başına bir hedef değil, sadece çözüm ise, yukarıdaki "temel gerçeklerden" herhangi biri doğrudan bir çözüm olarak kullanılabilir ve bir model eğitimi için kullanılamaz.

Umarım sorunuzu doğru anladım


Aynı soru için kod verebilirseniz, bu soru
cömert

görev nihayetinde metni elde etmek ama ilk önce içindeki tüm alfasayısal karakterleri tanımlamaya çalışıyorum, daha sonra aynı zaman için OCR kullanıyorum
Pulkit Bhatnagar

Ne teklif hiçbiri gerçekten bir çözüm değildir ve algoritmik kod kısa veya basit olmaz bence, bu yüzden fikirler düzeyinde bırakacağım :-). ps upvote için teşekkürler!
Yuri Feldman
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.