吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 515|回复: 1
收起左侧

[Python 原创] 基于密度聚类算法的通用怪物定位实现

[复制链接]
18834161486 发表于 2024-3-21 17:25
先上代码
[Python] 纯文本查看 复制代码
import cv2
import numpy as np
import wx
import wx.lib.scrolledpanel as scrolled
import wx.aui
from sklearn.cluster import DBSCAN


class MyFrame(wx.Frame):
    def __init__(self, parent, title):
        super(MyFrame, self).__init__(parent, title=title, size=(800, 600))
        self.mgr = wx.aui.AuiManager(self)
        # 创建第一个图片显示面板
        panel1 = scrolled.ScrolledPanel(self, -1)
        panel1.SetupScrolling()
        image_path1 = "1.jpg"
        self.image_bitmap1 = wx.Bitmap(image_path1, wx.BITMAP_TYPE_ANY)
        self.static_bitmap1 = wx.StaticBitmap(panel1, -1, self.image_bitmap1, pos=(10, 10))
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.static_bitmap1, 0, wx.ALL, 5)
        panel1.SetSizer(sizer)
        self.mgr.AddPane(panel1, wx.aui.AuiPaneInfo().Caption("Image 1").Left().BestSize(400, 600))

        self.Bind(wx.EVT_CONTEXT_MENU, self.on_context_menu)


        # 创建第二个图片显示面板
        panel2 = scrolled.ScrolledPanel(self, -1)
        panel2.SetupScrolling()
        self.image_bitmap2 = self.image_bitmap1  # 直接从第一张图片获取数据
        self.static_bitmap2 = wx.StaticBitmap(panel2, -1, self.image_bitmap2, pos=(10, 10))
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.static_bitmap2, 0, wx.ALL, 5)
        panel2.SetSizer(sizer)
        self.mgr.AddPane(panel2, wx.aui.AuiPaneInfo().Caption("Image 2").Right().BestSize(400, 600))

        # 创建输入框面板
        input_panel = wx.Panel(self)
        input_panel.SetMinSize((400, 600))  # 设置最小宽高为400x600
        input_sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.input1 = wx.TextCtrl(input_panel, -1, "")
        self.input2 = wx.TextCtrl(input_panel, -1, "")
        self.input3 = wx.TextCtrl(input_panel, -1, "")
        self.output_button = wx.Button(input_panel, label="显示")
        self.output_button.Bind(wx.EVT_BUTTON, self.on_output_button_click)
        input_sizer.Add(self.input1, 0, wx.ALL, 5)
        input_sizer.Add(self.input2, 0, wx.ALL, 5)
        input_sizer.Add(self.input3, 0, wx.ALL, 5)
        input_sizer.Add(self.output_button, 0, wx.ALL, 5)
        input_panel.SetSizer(input_sizer)
        self.mgr.AddPane(input_panel, wx.aui.AuiPaneInfo().Caption("Inputs").Bottom().BestSize(400, 50))
        self.mgr.Update()

    def on_context_menu(self, event):
        menu = wx.Menu()
        item = menu.Append(-1, "Replace Image")
        self.Bind(wx.EVT_MENU, self.on_replace_image, item)
        self.PopupMenu(menu)
        menu.Destroy()

    def on_replace_image(self, event):
        with wx.FileDialog(self, "Choose a file", wildcard="All files (*.*)|*.*",
                           style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog:
            if fileDialog.ShowModal() == wx.ID_CANCEL:
                return
            pathname = fileDialog.GetPath()
            self.update_image(pathname)
            new_bitmap2 = wx.Bitmap(pathname, wx.BITMAP_TYPE_ANY)
            self.image_bitmap2 = new_bitmap2

    def update_image(self, image_path):
        new_bitmap = wx.Bitmap(image_path, wx.BITMAP_TYPE_ANY)
        self.static_bitmap1.SetBitmap(new_bitmap)
        self.static_bitmap2.SetBitmap(new_bitmap)

    def on_output_button_click(self, event):
        input1_content = self.input1.GetValue()
        input2_content = self.input2.GetValue()
        input3_content = self.input3.GetValue()

        # 获取第二张图片数据
        image = self.bitmap_to_cv_image(self.image_bitmap2)
        processed_img = self.Stressshow(image, input1_content)
        processed_img = self.jl(processed_img, int(input2_content), int(input3_content))

        # 清空第二张图片面板数据
        self.static_bitmap2.SetBitmap(wx.Bitmap())

        # 显示处理后的图片在第二个图片面板中
        self.show_processed_image(processed_img, self.static_bitmap2)

    def show_processed_image(self, processed_image, image_panel):
        bitmap = self.cv_image_to_bitmap(processed_image)
        image_panel.SetBitmap(bitmap)

    def bitmap_to_cv_image(self, bitmap):
        bmp = bitmap.ConvertToImage()
        data = bmp.GetData()
        image = np.frombuffer(data, dtype=np.uint8)
        image = image.reshape(bmp.GetHeight(), bmp.GetWidth(), -1)
        image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
        return image

    def cv_image_to_bitmap(self, image):
        if len(image.shape) == 2:  # 处理灰度图像
            height, width = image.shape
            cv2_image_rgb = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)  # 将灰度图像转换为RGB格式
        elif len(image.shape) == 3:  # 处理彩色图像
            height, width, _ = image.shape
            cv2_image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)  # 将BGR格式转换为RGB格式
        else:
            raise ValueError('Unsupported image format')

        wx_image = wx.Image(width, height, cv2_image_rgb.tobytes())  # 创建wx.Image对象
        bitmap = wx.Bitmap(wx_image)  # 将wx.Image转换为Bitmap对象
        return bitmap

    def jl(self, img, eps=7, min=60):
        white_pixels = np.argwhere(img == 255)
        # # 使用DBSCAN进行像素聚类
        dbscan = DBSCAN(eps=eps, min_samples=min)
        labels = dbscan.fit_predict(white_pixels)
        for label in np.unique(labels):
            if label == -1:
                continue
            cluster = white_pixels[labels == label]
            x, y, w, h = cv2.boundingRect(cluster)
            img = cv2.rectangle(img, (y, x), (y + h, x + w), (125, 0, 0), 2)
        return img

    def parse_custom_color(self, color_string):
        r, g, b = int(color_string[4:6], 16), int(color_string[2:4], 16), int(color_string[0:2], 16)
        if len(color_string) > 6:
            dr, dg, db = int(color_string[7:9], 16), int(color_string[9:11], 16), int(color_string[11:13], 16)
        else:
            dr, dg, db = 0, 0, 0
        lower_rgb = np.array([max(0, r - dr), max(0, g - dg), max(0, b - db)], dtype=np.uint8)
        upper_rgb = np.array([min(255, r + dr), min(255, g + dg), min(255, b + db)], dtype=np.uint8)
        return lower_rgb, upper_rgb

    def Stressshow(self, img, colors):
        colors = colors.split("|")
        masks = np.zeros_like(img[:, :, 0], dtype=np.uint8)  # 创建与图像大小相同的空白掩膜
        for color in colors:
            lower_rgb, upper_rgb = self.parse_custom_color(color)
            mask = cv2.inRange(img, lower_rgb, upper_rgb)
            masks += mask
        # 将符合条件的颜色设为白色(255),不符合条件的设为黑色(0)
        result = np.where(masks > 0, 255, 0).astype(np.uint8)
        return result


app = wx.App(False)
frame = MyFrame(None, "My GUI")
frame.Show()
app.MainLoop()

再说一下原理:
首先呢,通过颜色的rgb值将怪物从地图上区分出来,那么受这个因素影响,怪物的颜色就不能和地图颜色太相近,要不然就分辨不出来。这里其实稍微做了一下优化,可以像大漠那样取多个点的颜色,也支持偏色。
然后呢,将怪物的颜色变为白色,将地图颜色变为黑色,这就可以把图像转换为一个二维数组了,直接进行数据处理。
接着呢,使用密度聚类算法筛选出符合条件的区域。这里关于密度聚类算法大家可以百度一下就能找到原理。
最后呢,我们需要传进去三个参数,一个是怪物的颜色描述,一个是密度聚类的半径大小,一个是密度聚类的点的数量,就看可以筛选出来怪物的位置。
这三个参数需要大家通过微调来实现精准控制。
讲一讲软件用法:
需要的库大家自行下载,直接运行会报错缺少图片,这个不影响,直接对最左边的窗口右键可以替换图片,然后在最下面的三个输入框输入我们需要的参数,点击按钮就可以在右边的窗口框选出结果。
因为论坛不支持bmp格式图片,就不附图了。

免费评分

参与人数 2威望 +1 吾爱币 +21 热心值 +2 收起 理由
苏紫方璇 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
gusong125 + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

gusong125 发表于 2024-3-21 23:46
强悍,支持楼主,不知道有没有寻路的解决方案基于图色的!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-29 13:28

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表