如何在Python中使用OpenCV检测图像中的线条?

问题描述 投票:0回答:1

我正在寻找一种使用 Python 和 OpenCV 库来检测图像中线条的方法。我应该使用哪些 OpenCV 函数来查找和确定图像中线条的位置?具体来说,如何使用图像处理技术来识别给定图像中最突出的线条?

您能否提供示例 Python 代码以及解释? 我希望程序做的是连续跟踪地毯照片从顶部到底部的线条。现在,我只处理照片,但最终我希望它能够根据现场镜头来完成此操作。你能帮我吗

谢谢你。 这段代码很简单

`import cv2
import numpy as np
import traceback
import logging
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
import os
import time

logging.basicConfig(filename='error_log.txt', level=logging.ERROR)


class ImageProcessor:
    def __init__(self):
        pass

    def process_image(self, image_path):
        try:
            start_time = time.time()

            original_image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)

            if original_image is None:
                raise Exception("Dosya yüklenemedi. Dosya yolunu kontrol edin.")

            marked_image = self.process_and_measure(original_image)

            cv2.imshow("Marked Image", marked_image)

            end_time = time.time()
            elapsed_time = (end_time - start_time) * 1000
            print(f"İşleme Süresi: {elapsed_time:.2f} ms")

            cv2.waitKey(0)
            cv2.destroyAllWindows()

        except Exception as e:
            logging.error(f'HATA: {str(e)}')
            traceback.print_exc()

    def process_and_measure(self, original_image):
        equalized_image = cv2.equalizeHist(original_image)

        clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8, 8))
        processed_image = clahe.apply(equalized_image)

        _, thresholded = cv2.threshold(processed_image, 200, 255, cv2.THRESH_BINARY)

        contours, _ = cv2.findContours(thresholded, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

        if contours:
            largest_contour = max(contours, key=cv2.contourArea)

            m = cv2.moments(largest_contour)

            average_x = int(m["m10"] / m["m00"])
            center_x = original_image.shape[1] // 2
            distance_from_center = average_x - center_x

            marked_image = cv2.cvtColor(original_image, cv2.COLOR_GRAY2BGR)
            cv2.line(marked_image, (center_x, 0), (center_x, original_image.shape[0]), (0, 0, 255), 2)
            cv2.line(marked_image, (average_x, 0), (average_x, original_image.shape[0]), (0, 255, 0), 2)

            font = cv2.FONT_HERSHEY_SIMPLEX
            cv2.putText(marked_image, f"{distance_from_center} px", (center_x + 10, original_image.shape[0] // 2), font,
                        0.7, (0, 0, 255), 2, cv2.LINE_AA)

            return marked_image

        else:
            return cv2.cvtColor(original_image, cv2.COLOR_GRAY2BGR)


class AdvancedInterface:
    def __init__(self, master):
        self.master = master
        self.master.title("Gelişmiş Arayüz")

        self.canvas = tk.Canvas(master, width=800, height=600, bg="white")
        self.canvas.grid(row=0, column=0, columnspan=4)

        self.btn_select_image = tk.Button(master, text="Resim Seç", command=self.select_image)
        self.btn_select_image.grid(row=1, column=0, padx=10, pady=10)

        self.btn_select_video = tk.Button(master, text="Video Seç", command=self.select_video)
        self.btn_select_video.grid(row=1, column=1, padx=10, pady=10)

        self.btn_capture_image = tk.Button(master, text="Kamera Görüntüsü", command=self.capture_image)
        self.btn_capture_image.grid(row=1, column=2, padx=10, pady=10)

        self.btn_up = tk.Button(master, text="↑", command=self.move_up, width=5, height=2)
        self.btn_up.grid(row=2, column=1, padx=5, pady=10)
        self.btn_down = tk.Button(master, text="↓", command=self.move_down, width=5, height=2)
        self.btn_down.grid(row=4, column=1, padx=5, pady=10)
        self.btn_left = tk.Button(master, text="←", command=self.move_left, width=5, height=2)
        self.btn_left.grid(row=3, column=0, padx=5, pady=10)
        self.btn_right = tk.Button(master, text="→", command=self.move_right, width=5, height=2)
        self.btn_right.grid(row=3, column=2, padx=5, pady=10)

        self.btn_exit = tk.Button(master, text="Programı Kapat", command=self.master.destroy)
        self.btn_exit.grid(row=5, column=0, columnspan=4, padx=10, pady=10)

        self.image_processor = ImageProcessor()

    def select_image(self):
        file_path = filedialog.askopenfilename(title="Resim Seç", filetypes=[("PNG files", "*.png")])
        if file_path:
            print("Seçilen Resim:", file_path)
            self.image_processor.process_image(file_path)

    def select_video(self):
        file_path = filedialog.askopenfilename(title="Video Seç", filetypes=[("Video Files", "*.mp4")])
        if file_path:
            print("Seçilen Video:", file_path)

    def capture_image(self):
        print("Kamera Görüntüsü Alındı")

    def move_up(self):
        print("Yukarı Hareket")

    def move_down(self):
        print("Aşağı Hareket")

    def move_left(self):
        print("Sol Hareket")

    def move_right(self):
        print("Sağ Hareket")


if __name__ == "__main__":
    root = tk.Tk()
    app = AdvancedInterface(root)
    root.mainloop()`
python image line detect
1个回答
0
投票

如果目标是确定子图像(在本例中为一条线)出现在给定图像中的位置/可能性,则可以使用 OpenCV 中的模板匹配函数:https://docs.opencv .org/3.4/d4/dc6/tutorial_py_template_matching.html

这是我的项目中的代码示例:

def findImage(img1:Image, img2:Image):
    res = cv2.matchTemplate(img1.data, img2.data, cv2.TM_CCOEFF_NORMED)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
    return max_val

在本例中,我使用了

Image
类的自定义实现,但是您真正需要做的修改是传递图像的“数据”(这通常是
np.array
版本)照片/实时视频)在
cv2.matchTemplate
功能中。如果您关心匹配的可能性,您可以使用任何
_NORMED
算法,因为这会将分数标准化为 0 到 1 之间。

在上面的示例中,我将两个图像传递到 matchTemplate 中,然后使用

cv2.minMaxLoc(res)
检索该子图像匹配的最小和最大分数,以及找到子图像的最小和最大位置。这对我的用例很有用,因为我只需要最高的似然得分,但如果一个图像中存在多条线,您可能需要手动探索
res
输出,因为这是一组表示图像质量的数据子图像与父图像中所有给定坐标的匹配。

(另外,我在这里假设您正在寻找的线条是一致的,并且裁剪出它们的外观样本并将其用作源

img1
数据与照片是微不足道的充当模板
img2
数据)

© www.soinside.com 2019 - 2024. All rights reserved.