AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 78968073
Accepted
Pubg Mobile
Pubg Mobile
Asked: 2024-09-10 13:57:21 +0800 CST2024-09-10 13:57:21 +0800 CST 2024-09-10 13:57:21 +0800 CST

Detectar apenas caixas mais à esquerda na imagem

  • 772

Tenho uma imagem JPG que contém nomes de marcas de dispositivos móveis:
insira a descrição da imagem aqui

Agora quero detectar o primeiro caractere de cada palavra pelo script python.
Escrevi o seguinte script python para isso:

import cv2
import numpy as np
from tkinter import Tk, Canvas, Frame, Scrollbar, BOTH, VERTICAL, HORIZONTAL
from PIL import Image, ImageTk

# Function to draw rectangles around shapes and display using Tkinter
def draw_rectangles(image_path):
    # Create a Tkinter window to display the image
    root = Tk()
    root.title("Image with Left-Most Rectangles Only")

    # Load the image
    image = cv2.imread(image_path)
    # Convert the image to grayscale
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # Apply adaptive thresholding to get better separation of text
    thresh = cv2.adaptiveThreshold(
        gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2
    )

    # Find contours in the binary image
    contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # Dictionary to store contours grouped by Y-coordinate ranges
    contours_by_y = {}

    # Sort contours by X-coordinate to ensure we pick the left-most character first
    sorted_contours = sorted(contours, key=lambda c: cv2.boundingRect(c)[0])

    # Group contours by their Y coordinate to keep only the left-most rectangle per Y range
    for contour in sorted_contours:
        x, y, w, h = cv2.boundingRect(contour)
        if w > 15 and h > 15:  # Adjust the size filter to remove small artifacts
            aspect_ratio = w / float(h)
            # Ensure the aspect ratio is within the typical range of letters
            if 0.2 < aspect_ratio < 5:
                y_range = y // 20  # Group by a smaller Y coordinate range for better separation

                # Check if the current rectangle is more left-most in X within its Y range
                if y_range not in contours_by_y:
                    contours_by_y[y_range] = (x, y, w, h)  # Store the first contour found in this range
                else:
                    # Compare and keep the left-most (smallest X) rectangle
                    current_x, _, _, _ = contours_by_y[y_range]
                    # Check distance between new contour and the existing one to avoid close detection
                    if x < current_x and (x - current_x) > 20:  # Distance threshold to filter out close contours
                        contours_by_y[y_range] = (x, y, w, h)

    # Draw only the left-most rectangles
    for (x, y, w, h) in contours_by_y.values():
        cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)  # Red color in BGR

    # Convert the image to RGB (OpenCV uses BGR by default)
    image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

    # Convert the image to a format Tkinter can use
    image_pil = Image.fromarray(image_rgb)
    image_tk = ImageTk.PhotoImage(image_pil)

    # Create a frame for the Canvas and scrollbars
    frame = Frame(root)
    frame.pack(fill=BOTH, expand=True)

    # Create a Canvas widget to display the image
    canvas = Canvas(frame, width=image_tk.width(), height=image_tk.height())
    canvas.pack(side="left", fill="both", expand=True)

    # Add scrollbars to the Canvas
    v_scrollbar = Scrollbar(frame, orient=VERTICAL, command=canvas.yview)
    v_scrollbar.pack(side="right", fill="y")

    h_scrollbar = Scrollbar(frame, orient=HORIZONTAL, command=canvas.xview)
    h_scrollbar.pack(side="bottom", fill="x")

    canvas.configure(yscrollcommand=v_scrollbar.set, xscrollcommand=h_scrollbar.set)
    canvas.create_image(0, 0, anchor="nw", image=image_tk)
    canvas.config(scrollregion=canvas.bbox("all"))

    # Keep a reference to the image to prevent garbage collection
    canvas.image = image_tk

    root.mainloop()

# Path to your image
image_path = r"E:\Desktop\mobile_brands\ORG_027081-Recovered.jpg"

# Call the function
draw_rectangles(image_path)

Mas não sei por que não está funcionando bem. A precisão desse script é de 90%. Por exemplo, na imagem acima, ele detecta o caractere "a" em "Samsung"
insira a descrição da imagem aqui

onde está o problema do meu script?
Como posso consertar esse problema?
talvez pela coordenada Y e X não consiga detectar as caixas mais à esquerda na imagem.
Note que não quero usar OCR

python
  • 1 1 respostas
  • 58 Views

1 respostas

  • Voted
  1. Best Answer
    acw1668
    2024-09-10T15:40:49+08:002024-09-10T15:40:49+08:00

    Primeiro, classificarei esses contornos pela coordenada y, depois agruparei os contornos classificados por linhas. Por fim, desenharei o mais à esquerda em cada linha:

    # Sort contours by Y-coordinate
    sorted_contours = sorted(contours, key=lambda c: cv2.boundingRect(c)[1])
    
    # group contours by row
    last_y = None
    rows = []
    for contour in sorted_contours:
        x, y, w, h = cv2.boundingRect(contour)
        if w > 15 or h > 15:
            if last_y is None or abs(last_y-y) > 50:  # 50 is for provided image, it may not work for other image
                # this is a new row
                rows.append([])
                last_y = y  # save the reference y-coordinate
            rows[-1].append((x, y, w, h)) # append item into current row
    
    for row in rows:
        # show left-most one in current row
        x, y, w, h = sorted(row, key=lambda x: x[0])[0]
        cv2.rectangle(image, (x, y), (x+w, y+h), (0, 0, 255), 2)
    

    Observe que presumo que a diferença da coordenada y entre as linhas seja maior que 50 pixels.

    Resultado:

    insira a descrição da imagem aqui

    • 1

relate perguntas

  • Como divido o loop for em 3 quadros de dados individuais?

  • Como verificar se todas as colunas flutuantes em um Pandas DataFrame são aproximadamente iguais ou próximas

  • Como funciona o "load_dataset", já que não está detectando arquivos de exemplo?

  • Por que a comparação de string pandas.eval() retorna False

  • Python tkinter/ ttkboostrap dateentry não funciona quando no estado somente leitura

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle?

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Quando devo usar um std::inplace_vector em vez de um std::vector?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Martin Hope
    Aleksandr Dubinsky Por que a correspondência de padrões com o switch no InetAddress falha com 'não cobre todos os valores de entrada possíveis'? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer Quando devo usar um std::inplace_vector em vez de um std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB Por que o GCC gera código que executa condicionalmente uma implementação SIMD? 2024-02-17 06:17:14 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve