You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenCV绘画板无法切换铅笔颜色问题求助

问题分析与解决

核心问题

你代码里的关键错误是重复设置鼠标回调函数:

cv2.setMouseCallback('image', change_Tool)
cv2.setMouseCallback('image', draw_circle)

OpenCV每个窗口只能绑定一个鼠标回调函数,第二次调用会直接覆盖第一次,导致change_Tool函数完全不会被执行,右键点击工具区自然无法切换颜色。

另外还有两个小问题:

  • 初始color设为None,虽然当前能画黑色是OpenCV的默认行为,但逻辑上不严谨,容易出问题。
  • 用range()判断坐标范围会漏掉边界值(比如x=123时,range(5,123)不包含123),导致点击工具区边缘时无法触发颜色切换。

修正方案

  1. 合并鼠标回调函数:把右键切换工具和左键绘制的逻辑放到同一个函数里。
  2. 修正坐标判断逻辑:用>=和<=代替range(),确保所有工具区的坐标都能被正确识别。
  3. 初始化默认颜色:把color初始化为铅笔的黑色,符合初始预期。

修正后的完整代码

import cv2
import numpy as np

# 创建601*601的白色画布
img = np.ones((601, 601, 3), np.uint8) * 255

class Tools:
    def __init__(self, points: list, color) -> None:
        self.points = points
        self.color = color
        # 绘制工具区域
        cv2.rectangle(img, self.points[0], self.points[1], self.color, -1)

# 初始化默认颜色为黑色(铅笔)
color = (0, 0, 0)

def mouse_callback(event, x, y, flags, param):
    global color
    # 右键点击切换工具颜色
    if event == cv2.EVENT_RBUTTONDOWN:
        # 用>=和<=判断坐标,覆盖完整工具区域
        if pencil.points[0][0] <= x <= pencil.points[1][0] and 560 <= y <= 594:
            color = pencil.color
        elif eraser.points[0][0] <= x <= eraser.points[1][0] and 560 <= y <= 594:
            color = eraser.color
        elif green.points[0][0] <= x <= green.points[1][0] and 560 <= y <= 594:
            color = green.color
        elif red.points[0][0] <= x <= red.points[1][0] and 560 <= y <= 594:
            color = red.color
        elif blue.points[0][0] <= x <= blue.points[1][0] and 560 <= y <= 594:
            color = blue.color
    # 左键点击绘制圆形
    elif event == cv2.EVENT_LBUTTONDOWN:
        cv2.circle(img, (x, y), 20, color, -1)

# 初始化工具
pencil = Tools([(5, 560), (123, 594)], (0, 0, 0))
eraser = Tools([(123, 560), (241, 594)], (255, 255, 255))
green = Tools([(241, 560), (359, 594)], (0, 255, 0))
red = Tools([(359, 560), (477, 594)], (255, 0, 0))
blue = Tools([(477, 560), (595, 594)], (0, 0, 255))

cv2.namedWindow('image')
# 只绑定一次合并后的鼠标回调函数
cv2.setMouseCallback('image', mouse_callback)

while True:
    cv2.imshow('image', img)
    # 按ESC键退出
    if cv2.waitKey(1) & 0xFF == 27:
        break
cv2.destroyAllWindows()

验证效果

  • 右键点击底部的任意工具色块,切换对应的绘画颜色
  • 左键点击画布任意位置,用当前选中的颜色绘制圆形
  • 点击橡皮擦工具后,左键绘制的白色圆形会覆盖原有内容,实现擦除效果

内容的提问来源于stack exchange,提问作者Hadi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 03:57:48