diff --git a/bb_chart_2026_03_02.html b/bb_chart_2026_03_02.html
new file mode 100644
index 0000000..2533fdb
--- /dev/null
+++ b/bb_chart_2026_03_02.html
@@ -0,0 +1,145 @@
+
+
+
+
+ ETHUSDT 2026-03-02 K线 + 布林带
+
+
+
+
+
+
+
+
+
diff --git a/bb_trade_log_20260301.txt b/bb_trade_log_20260301.txt
deleted file mode 100644
index 342ab27..0000000
--- a/bb_trade_log_20260301.txt
+++ /dev/null
@@ -1,368 +0,0 @@
-
-============================================================
-时间: 2026-03-01 03:34:26
-操作: 加仓空#1
-价格: 1945.80
-BB上轨: 1942.91 | 中轨: 1928.45 | 下轨: 1913.99
-原因: 价格最高1945.80触及上轨1942.91,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 03:35:28
-操作: 加仓空#2
-价格: 1946.06
-BB上轨: 1947.60 | 中轨: 1930.12 | 下轨: 1912.64
-原因: 价格最高1948.81触及上轨1947.60,BB(10,2.5) (加仓#2/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 04:20:55
-操作: 加仓空#3
-价格: 1956.54
-BB上轨: 1958.72 | 中轨: 1947.07 | 下轨: 1935.42
-原因: 价格最高1963.78触及上轨1958.72,BB(10,2.5) (加仓#3/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 06:37:04
-操作: 开空
-价格: 1981.98
-BB上轨: 1971.65 | 中轨: 1961.60 | 下轨: 1951.55
-原因: 价格最高1982.00触及上轨1971.65,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-01 08:04:15
-操作: 加仓空#1
-价格: 1968.36
-BB上轨: 1967.65 | 中轨: 1961.56 | 下轨: 1955.46
-原因: 价格最高1968.37触及上轨1967.65,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 09:11:15
-操作: 翻转: 平空→开多
-价格: 1948.38
-BB上轨: 1965.27 | 中轨: 1957.74 | 下轨: 1950.20
-原因: 价格最低1948.07触及下轨1950.20,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-01 09:15:44
-操作: 加仓多#1
-价格: 1946.42
-BB上轨: 1966.34 | 中轨: 1956.43 | 下轨: 1946.53
-原因: 价格最低1946.20触及下轨1946.53,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 09:37:21
-操作: 翻转: 平多→开空
-价格: 1966.51
-BB上轨: 1967.60 | 中轨: 1955.23 | 下轨: 1942.85
-原因: 价格最高1967.64触及上轨1967.60,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-01 09:47:41
-操作: 加仓空#1
-价格: 1974.91
-BB上轨: 1973.88 | 中轨: 1956.84 | 下轨: 1939.80
-原因: 价格最高1974.91触及上轨1973.88,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 09:50:10
-操作: 加仓空#2
-价格: 1990.01
-BB上轨: 1988.73 | 中轨: 1959.52 | 下轨: 1930.30
-原因: 价格最高1991.56触及上轨1988.73,BB(10,2.5) (加仓#2/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 09:59:41
-操作: 开空
-价格: 2009.09
-BB上轨: 2008.95 | 中轨: 1964.55 | 下轨: 1920.15
-原因: 价格最高2009.20触及上轨2008.95,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-01 10:02:15
-操作: 加仓空#1
-价格: 2023.05
-BB上轨: 2025.72 | 中轨: 1970.39 | 下轨: 1915.07
-原因: 价格最高2026.00触及上轨2025.72,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 11:22:14
-操作: 开多
-价格: 2028.59
-BB上轨: 2042.05 | 中轨: 2035.46 | 下轨: 2028.87
-原因: 价格最低2028.58触及下轨2028.87,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-01 11:54:08
-操作: 加仓多#1
-价格: 2023.39
-BB上轨: 2039.59 | 中轨: 2032.27 | 下轨: 2024.96
-原因: 价格最低2021.86触及下轨2024.96,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 11:55:14
-操作: 加仓多#2
-价格: 2020.39
-BB上轨: 2042.34 | 中轨: 2030.59 | 下轨: 2018.84
-原因: 价格最低2018.50触及下轨2018.84,BB(10,2.5) (加仓#2/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 12:15:00
-操作: 加仓多#3
-价格: 2012.23
-BB上轨: 2039.99 | 中轨: 2026.95 | 下轨: 2013.91
-原因: 价格最低2008.07触及下轨2013.91,BB(10,2.5) (加仓#3/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 13:20:34
-操作: 翻转: 平多→开空
-价格: 2017.26
-BB上轨: 2017.21 | 中轨: 2014.22 | 下轨: 2011.24
-原因: 价格最高2017.47触及上轨2017.21,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-01 13:25:07
-操作: 加仓空#1
-价格: 2021.89
-BB上轨: 2021.00 | 中轨: 2015.09 | 下轨: 2009.17
-原因: 价格最高2021.58触及上轨2021.00,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 13:55:06
-操作: 翻转: 平空→开多
-价格: 2009.30
-BB上轨: 2023.23 | 中轨: 2016.18 | 下轨: 2009.13
-原因: 价格最低2008.73触及下轨2009.13,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-01 14:04:49
-操作: 加仓多#1
-价格: 2005.00
-BB上轨: 2024.71 | 中轨: 2015.13 | 下轨: 2005.56
-原因: 价格最低2005.00触及下轨2005.56,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 14:05:27
-操作: 加仓多#2
-价格: 2001.68
-BB上轨: 2026.45 | 中轨: 2014.43 | 下轨: 2002.41
-原因: 价格最低2001.68触及下轨2002.41,BB(10,2.5) (加仓#2/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 14:10:46
-操作: 加仓多#3
-价格: 1993.93
-BB上轨: 2029.77 | 中轨: 2012.76 | 下轨: 1995.76
-原因: 价格最低1993.62触及下轨1995.76,BB(10,2.5) (加仓#3/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 15:12:06
-操作: 翻转: 平多→开空
-价格: 2003.74
-BB上轨: 2003.48 | 中轨: 1996.50 | 下轨: 1989.52
-原因: 价格最高2003.74触及上轨2003.48,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-01 15:22:02
-操作: 加仓空#1
-价格: 2004.51
-BB上轨: 2004.32 | 中轨: 1996.69 | 下轨: 1989.06
-原因: 价格最高2004.51触及上轨2004.32,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 15:39:37
-操作: 加仓空#2
-价格: 2006.49
-BB上轨: 2005.89 | 中轨: 1998.49 | 下轨: 1991.09
-原因: 价格最高2007.16触及上轨2005.89,BB(10,2.5) (加仓#2/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 15:40:18
-操作: 加仓空#3
-价格: 2005.95
-BB上轨: 2008.50 | 中轨: 1999.85 | 下轨: 1991.20
-原因: 价格最高2008.89触及上轨2008.50,BB(10,2.5) (加仓#3/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 16:47:20
-操作: 翻转: 平空→开多
-价格: 1997.54
-BB上轨: 2011.42 | 中轨: 2004.66 | 下轨: 1997.89
-原因: 价格最低1997.54触及下轨1997.89,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-01 16:50:39
-操作: 加仓多#1
-价格: 1994.11
-BB上轨: 2012.88 | 中轨: 2003.62 | 下轨: 1994.36
-原因: 价格最低1994.00触及下轨1994.36,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 16:55:10
-操作: 加仓多#2
-价格: 1984.53
-BB上轨: 2019.59 | 中轨: 2002.06 | 下轨: 1984.53
-原因: 价格最低1984.04触及下轨1984.53,BB(10,2.5) (加仓#2/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 17:02:18
-操作: 加仓多#3
-价格: 1977.78
-BB上轨: 2021.30 | 中轨: 2000.09 | 下轨: 1978.87
-原因: 价格最低1977.34触及下轨1978.87,BB(10,2.5) (加仓#3/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 18:26:31
-操作: 翻转: 平多→开空
-价格: 1981.80
-BB上轨: 1982.79 | 中轨: 1979.44 | 下轨: 1976.08
-原因: 价格最高1982.80触及上轨1982.79,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-01 18:30:23
-操作: 加仓空#1
-价格: 1985.00
-BB上轨: 1984.64 | 中轨: 1979.89 | 下轨: 1975.13
-原因: 价格最高1985.00触及上轨1984.64,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 18:35:09
-操作: 加仓空#2
-价格: 1986.68
-BB上轨: 1986.58 | 中轨: 1980.49 | 下轨: 1974.40
-原因: 价格最高1986.68触及上轨1986.58,BB(10,2.5) (加仓#2/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 19:16:32
-操作: 加仓空#3
-价格: 1987.27
-BB上轨: 1987.94 | 中轨: 1983.79 | 下轨: 1979.63
-原因: 价格最高1987.96触及上轨1987.94,BB(10,2.5) (加仓#3/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 20:28:43
-操作: 翻转: 平空→开多
-价格: 1979.84
-BB上轨: 1987.42 | 中轨: 1983.66 | 下轨: 1979.90
-原因: 价格最低1979.64触及下轨1979.90,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-01 20:34:05
-操作: 加仓多#1
-价格: 1978.24
-BB上轨: 1987.88 | 中轨: 1983.22 | 下轨: 1978.55
-原因: 价格最低1978.24触及下轨1978.55,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 21:20:40
-操作: 加仓多#2
-价格: 1973.00
-BB上轨: 1982.99 | 中轨: 1978.04 | 下轨: 1973.10
-原因: 价格最低1973.00触及下轨1973.10,BB(10,2.5) (加仓#2/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 21:51:21
-操作: 翻转: 平多→开空
-价格: 1981.17
-BB上轨: 1980.40 | 中轨: 1976.08 | 下轨: 1971.77
-原因: 价格最高1981.82触及上轨1980.40,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-01 21:55:09
-操作: 开空
-价格: 2019.50
-BB上轨: 2011.12 | 中轨: 1980.16 | 下轨: 1949.21
-原因: 价格最高2019.50触及上轨2011.12,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-01 22:42:31
-操作: 翻转: 平空→开多
-价格: 1998.46
-BB上轨: 2021.45 | 中轨: 2010.61 | 下轨: 1999.77
-原因: 价格最低1997.98触及下轨1999.77,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-01 22:45:18
-操作: 加仓多#1
-价格: 1995.73
-BB上轨: 2021.76 | 中轨: 2008.71 | 下轨: 1995.66
-原因: 价格最低1995.55触及下轨1995.66,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 23:17:24
-操作: 翻转: 平多→开空
-价格: 2011.33
-BB上轨: 2011.41 | 中轨: 2003.47 | 下轨: 1995.52
-原因: 价格最高2011.70触及上轨2011.41,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-01 23:20:33
-操作: 加仓空#1
-价格: 2013.00
-BB上轨: 2012.52 | 中轨: 2003.72 | 下轨: 1994.92
-原因: 价格最高2013.00触及上轨2012.52,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 23:28:46
-操作: 加仓空#2
-价格: 2012.26
-BB上轨: 2012.18 | 中轨: 2003.62 | 下轨: 1995.05
-原因: 价格最高2012.30触及上轨2012.18,BB(10,2.5) (加仓#2/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 23:34:42
-操作: 加仓空#3
-价格: 2012.90
-BB上轨: 2013.39 | 中轨: 2003.97 | 下轨: 1994.56
-原因: 价格最高2013.42触及上轨2013.39,BB(10,2.5) (加仓#3/3)
-============================================================
-
-============================================================
-时间: 2026-03-01 23:57:04
-操作: 翻转: 平空→开多
-价格: 2000.60
-BB上轨: 2017.24 | 中轨: 2008.93 | 下轨: 2000.62
-原因: 价格最低2000.38触及下轨2000.62,BB(10,2.5)
-============================================================
diff --git a/bb_trade_log_20260302.txt b/bb_trade_log_20260302.txt
deleted file mode 100644
index 6947ebf..0000000
--- a/bb_trade_log_20260302.txt
+++ /dev/null
@@ -1,160 +0,0 @@
-
-============================================================
-时间: 2026-03-02 00:00:12
-操作: 加仓多#1
-价格: 1993.03
-BB上轨: 2022.56 | 中轨: 2007.82 | 下轨: 1993.08
-原因: 价格最低1992.31触及下轨1993.08,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-02 00:47:35
-操作: 加仓多#2
-价格: 1991.52
-BB上轨: 2009.23 | 中轨: 2000.42 | 下轨: 1991.62
-原因: 价格最低1991.22触及下轨1991.62,BB(10,2.5) (加仓#2/3)
-============================================================
-
-============================================================
-时间: 2026-03-02 00:50:07
-操作: 加仓多#3
-价格: 1972.92
-BB上轨: 2020.78 | 中轨: 1998.46 | 下轨: 1976.14
-原因: 价格最低1972.33触及下轨1976.14,BB(10,2.5) (加仓#3/3)
-============================================================
-
-============================================================
-时间: 2026-03-02 02:54:45
-操作: 翻转: 平空→开多
-价格: 1975.78
-BB上轨: 1987.69 | 中轨: 1981.61 | 下轨: 1975.53
-原因: 价格最低1974.35触及下轨1975.53,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-02 02:55:32
-操作: 加仓多#1
-价格: 1972.67
-BB上轨: 1988.35 | 中轨: 1980.89 | 下轨: 1973.42
-原因: 价格最低1972.66触及下轨1973.42,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-02 03:01:38
-操作: 加仓多#2
-价格: 1973.37
-BB上轨: 1985.83 | 中轨: 1979.58 | 下轨: 1973.32
-原因: 价格最低1972.87触及下轨1973.32,BB(10,2.5) (加仓#2/3)
-============================================================
-
-============================================================
-时间: 2026-03-02 03:06:27
-操作: 加仓多#3
-价格: 1969.61
-BB上轨: 1986.78 | 中轨: 1978.35 | 下轨: 1969.93
-原因: 价格最低1968.00触及下轨1969.93,BB(10,2.5) (加仓#3/3)
-============================================================
-
-============================================================
-时间: 2026-03-02 04:10:24
-操作: 开多
-价格: 1938.14
-BB上轨: 1968.16 | 中轨: 1954.01 | 下轨: 1939.86
-原因: 价格最低1932.00触及下轨1939.86,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-02 04:15:20
-操作: 加仓多#1
-价格: 1931.04
-BB上轨: 1971.27 | 中轨: 1951.22 | 下轨: 1931.16
-原因: 价格最低1931.04触及下轨1931.16,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-02 05:21:09
-操作: 翻转: 平多→开空
-价格: 1925.01
-BB上轨: 1925.19 | 中轨: 1914.61 | 下轨: 1904.03
-原因: 价格最高1926.00触及上轨1925.19,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-02 06:03:53
-操作: 加仓空#1
-价格: 1930.73
-BB上轨: 1930.55 | 中轨: 1925.10 | 下轨: 1919.65
-原因: 价格最高1930.73触及上轨1930.55,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-02 06:13:08
-操作: 加仓空#2
-价格: 1933.10
-BB上轨: 1930.98 | 中轨: 1926.37 | 下轨: 1921.75
-原因: 价格最高1933.10触及上轨1930.98,BB(10,2.5) (加仓#2/3)
-============================================================
-
-============================================================
-时间: 2026-03-02 06:15:10
-操作: 开空
-价格: 1944.64
-BB上轨: 1942.77 | 中轨: 1928.24 | 下轨: 1913.72
-原因: 价格最高1945.94触及上轨1942.77,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-02 08:07:31
-操作: 加仓空#1
-价格: 1943.79
-BB上轨: 1945.86 | 中轨: 1937.82 | 下轨: 1929.77
-原因: 价格最高1945.97触及上轨1945.86,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-02 08:10:09
-操作: 加仓空#2
-价格: 1950.40
-BB上轨: 1948.66 | 中轨: 1938.79 | 下轨: 1928.92
-原因: 价格最高1950.40触及上轨1948.66,BB(10,2.5) (加仓#2/3)
-============================================================
-
-============================================================
-时间: 2026-03-02 08:32:48
-操作: 加仓空#3
-价格: 1950.23
-BB上轨: 1950.72 | 中轨: 1942.27 | 下轨: 1933.83
-原因: 价格最高1950.89触及上轨1950.72,BB(10,2.5) (加仓#3/3)
-============================================================
-
-============================================================
-时间: 2026-03-02 09:10:45
-操作: 开空
-价格: 1980.63
-BB上轨: 1979.30 | 中轨: 1956.47 | 下轨: 1933.64
-原因: 价格最高1982.52触及上轨1979.30,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-02 10:06:29
-操作: 翻转: 平空→开多
-价格: 1956.56
-BB上轨: 1977.03 | 中轨: 1966.90 | 下轨: 1956.77
-原因: 价格最低1956.32触及下轨1956.77,BB(10,2.5)
-============================================================
-
-============================================================
-时间: 2026-03-02 10:10:10
-操作: 加仓多#1
-价格: 1948.99
-BB上轨: 1978.42 | 中轨: 1964.20 | 下轨: 1949.99
-原因: 价格最低1948.98触及下轨1949.99,BB(10,2.5) (加仓#1/3)
-============================================================
-
-============================================================
-时间: 2026-03-02 10:19:45
-操作: 加仓多#2
-价格: 1941.70
-BB上轨: 1981.96 | 中轨: 1961.75 | 下轨: 1941.53
-原因: 价格最低1941.34触及下轨1941.53,BB(10,2.5) (加仓#2/3)
-============================================================
diff --git a/captcha_clip.py b/captcha_clip.py
deleted file mode 100644
index 19f6811..0000000
--- a/captcha_clip.py
+++ /dev/null
@@ -1,113 +0,0 @@
-"""
-用 CLIP 做图块相似度匹配,在大图中找模板图标位置
-原理:把大图切成滑动窗口小块,用 CLIP 计算每块和模板的视觉相似度,取最高分的块
-"""
-import cv2
-import numpy as np
-from PIL import Image
-import torch
-from transformers import CLIPProcessor, CLIPModel
-from pathlib import Path
-
-BASE = Path(__file__).parent / "images"
-MODEL_NAME = "openai/clip-vit-base-patch32" # 约600MB,小模型
-
-
-def load_clip():
- print("加载 CLIP 模型(约600MB,首次自动下载)...")
- model = CLIPModel.from_pretrained(MODEL_NAME).to("cuda")
- processor = CLIPProcessor.from_pretrained(MODEL_NAME)
- print("CLIP 加载完成")
- return model, processor
-
-
-def find_by_clip(model, processor, main_img: np.ndarray, template_img: np.ndarray,
- step=10, win_sizes=None):
- """
- 滑动窗口 + CLIP 相似度,找模板在大图中的最佳位置
- """
- if win_sizes is None:
- th, tw = template_img.shape[:2]
- # 尝试原始尺寸及上下浮动
- win_sizes = [(int(tw * s), int(th * s)) for s in [0.8, 0.9, 1.0, 1.1, 1.2]]
-
- # 预处理模板
- tmpl_pil = Image.fromarray(cv2.cvtColor(template_img, cv2.COLOR_BGR2RGB))
- tmpl_inputs = processor(images=tmpl_pil, return_tensors="pt").to("cuda")
- with torch.no_grad():
- tmpl_out = model.vision_model(**tmpl_inputs)
- tmpl_feat = model.visual_projection(tmpl_out.pooler_output).float()
- tmpl_feat = tmpl_feat / tmpl_feat.norm(dim=-1, keepdim=True)
-
- mh, mw = main_img.shape[:2]
- best_score = -1
- best_box = None
-
- for (ww, wh) in win_sizes:
- if ww > mw or wh > mh:
- continue
- for y in range(0, mh - wh + 1, step):
- for x in range(0, mw - ww + 1, step):
- crop = main_img[y:y+wh, x:x+ww]
- crop_pil = Image.fromarray(cv2.cvtColor(crop, cv2.COLOR_BGR2RGB))
- crop_inputs = processor(images=crop_pil, return_tensors="pt").to("cuda")
- with torch.no_grad():
- crop_out = model.vision_model(**crop_inputs)
- crop_feat = model.visual_projection(crop_out.pooler_output).float()
- crop_feat = crop_feat / crop_feat.norm(dim=-1, keepdim=True)
- score = (tmpl_feat * crop_feat).sum().item()
- if score > best_score:
- best_score = score
- best_box = (x, y, ww, wh)
-
- return best_box, best_score
-
-
-def main():
- main_img = cv2.imread(str(BASE / "1.jpg"))
- templates = {
- "2.png": cv2.imread(str(BASE / "2.png")),
- "3.png": cv2.imread(str(BASE / "3.png")),
- "4.png": cv2.imread(str(BASE / "4.png")),
- }
-
- # 模板是 BGRA,转 BGR
- for name in templates:
- img = cv2.imread(str(BASE / name), cv2.IMREAD_UNCHANGED)
- if img.shape[2] == 4:
- # alpha 通道合成白底
- alpha = img[:, :, 3:4] / 255.0
- rgb = img[:, :, :3].astype(float)
- white = np.ones_like(rgb) * 255
- merged = (rgb * alpha + white * (1 - alpha)).astype(np.uint8)
- templates[name] = merged
- else:
- templates[name] = img
-
- model, processor = load_clip()
-
- vis = main_img.copy()
- colors = {"2.png": (0, 0, 255), "3.png": (0, 255, 0), "4.png": (255, 0, 0)}
-
- print()
- for name, tmpl in templates.items():
- print(f"正在匹配 {name} ...")
- box, score = find_by_clip(model, processor, main_img, tmpl, step=8)
- if box:
- x, y, w, h = box
- cx, cy = x + w // 2, y + h // 2
- color = colors[name]
- cv2.rectangle(vis, (x, y), (x+w, y+h), color, 2)
- cv2.circle(vis, (cx, cy), 5, color, -1)
- cv2.putText(vis, name, (x, y-5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 1)
- print(f" {name}: 中心点 ({cx}, {cy}) 相似度={score:.4f}")
- else:
- print(f" {name}: 未找到")
-
- out = BASE / "result_clip.jpg"
- cv2.imwrite(str(out), vis)
- print(f"\n结果保存到: {out}")
-
-
-if __name__ == "__main__":
- main()
diff --git a/captcha_vl.py b/captcha_vl.py
deleted file mode 100644
index d60605d..0000000
--- a/captcha_vl.py
+++ /dev/null
@@ -1,131 +0,0 @@
-"""
-用 Qwen2-VL 本地模型识别验证码图片位置
-首次运行会自动下载模型(约 4GB)
-"""
-import base64
-from pathlib import Path
-from transformers import Qwen2VLForConditionalGeneration, AutoProcessor
-from qwen_vl_utils import process_vision_info
-import torch
-
-MODEL_NAME = "Qwen/Qwen2-VL-7B-Instruct"
-BASE = Path(__file__).parent / "images"
-
-def img_to_base64(path):
- with open(path, "rb") as f:
- return base64.b64encode(f.read()).decode()
-
-def load_model():
- print("加载模型中(首次运行会下载约15GB)...")
- from transformers import BitsAndBytesConfig
- bnb_config = BitsAndBytesConfig(
- load_in_4bit=True,
- bnb_4bit_compute_dtype=torch.float16,
- bnb_4bit_use_double_quant=True,
- bnb_4bit_quant_type="nf4",
- )
- model = Qwen2VLForConditionalGeneration.from_pretrained(
- MODEL_NAME,
- quantization_config=bnb_config,
- device_map="cuda",
- )
- processor = AutoProcessor.from_pretrained(MODEL_NAME)
- print("模型加载完成")
- return model, processor
-
-def ask_one(model, processor, main_img_path, template_path):
- """让模型找出单个模板图在主图中的位置,返回原始回答"""
- messages = [
- {
- "role": "user",
- "content": [
- {
- "type": "text",
- "text": (
- "下面是一张背景大图(300x200像素),"
- "以及一个需要在大图中找到的小图标轮廓。\n"
- "大图:"
- )
- },
- {"type": "image", "image": str(main_img_path)},
- {
- "type": "text",
- "text": "\n小图标轮廓(这个图标出现在大图中某个物体上):"
- },
- {"type": "image", "image": str(template_path)},
- {
- "type": "text",
- "text": (
- "\n请仔细观察小图标的形状,在大图中找到形状最相似的物体,"
- "给出该物体中心点的像素坐标。"
- "坐标原点在左上角,x向右,y向下。"
- "只需回答坐标,格式:(x, y)"
- )
- }
- ]
- }
- ]
-
- text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
- image_inputs, video_inputs = process_vision_info(messages)
- inputs = processor(
- text=[text],
- images=image_inputs,
- videos=video_inputs,
- padding=True,
- return_tensors="pt",
- ).to("cuda")
-
- with torch.no_grad():
- generated_ids = model.generate(**inputs, max_new_tokens=50)
-
- generated_ids_trimmed = [
- out_ids[len(in_ids):] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
- ]
- output = processor.batch_decode(
- generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False
- )
- return output[0].strip()
-
-
-def main():
- main_img = BASE / "1.jpg"
- templates = [BASE / "2.png", BASE / "3.png", BASE / "4.png"]
-
- model, processor = load_model()
-
- import re
- import cv2
-
- img = cv2.imread(str(main_img))
- colors = {"2.png": (0, 0, 255), "3.png": (0, 255, 0), "4.png": (255, 0, 0)}
- results = {}
-
- for tmpl_path in templates:
- name = tmpl_path.name
- print(f"\n正在识别 {name} ...")
- answer = ask_one(model, processor, main_img, tmpl_path)
- print(f"{name} 模型回答: {answer}")
-
- match = re.search(r"\((\d+)[,,\s]+(\d+)\)", answer)
- if match:
- x, y = int(match.group(1)), int(match.group(2))
- results[name] = (x, y)
- color = colors[name]
- cv2.circle(img, (x, y), 8, color, -1)
- cv2.circle(img, (x, y), 12, color, 2)
- cv2.putText(img, name, (x + 14, y + 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 1)
- else:
- print(f"{name}: 未能解析坐标,原始回答: {answer}")
-
- print("\n=== 点击坐标汇总 ===")
- for name, (x, y) in results.items():
- print(f"{name}: ({x}, {y})")
-
- out = BASE / "result_vl.jpg"
- cv2.imwrite(str(out), img)
- print(f"\n可视化结果保存到: {out}")
-
-
-if __name__ == "__main__":
- main()
diff --git a/credentials.json b/credentials.json
deleted file mode 100644
index 08d7b9d..0000000
--- a/credentials.json
+++ /dev/null
@@ -1 +0,0 @@
-{"installed":{"client_id":"823839778551-mgovppr13aoil1r69upj7uiv84ej0sih.apps.googleusercontent.com","project_id":"gen-lang-client-0535910705","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"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","redirect_uris":["http://localhost"]}}
\ No newline at end of file
diff --git a/find_captcha.py b/find_captcha.py
deleted file mode 100644
index 59a053e..0000000
--- a/find_captcha.py
+++ /dev/null
@@ -1,127 +0,0 @@
-"""
-验证码图片匹配脚本
-在 1.jpg 中找到 2.png、3.png、4.png 的位置
-"""
-import cv2
-import numpy as np
-import os
-
-def find_template_in_image(main_img_path, template_path, threshold=0.5):
- """
- 在主图中查找模板图片的位置(原始尺寸 + 多尺度)
- 支持 PNG alpha 通道作为模板轮廓
- 返回置信度最高的匹配结果
- """
- main_img = cv2.imread(main_img_path)
- template = cv2.imread(template_path, cv2.IMREAD_UNCHANGED)
-
- if main_img is None:
- print(f"无法读取主图: {main_img_path}")
- return []
- if template is None:
- print(f"无法读取模板: {template_path}")
- return []
-
- h, w = template.shape[:2]
- main_gray = cv2.cvtColor(main_img, cv2.COLOR_BGR2GRAY)
-
- # 如果模板有 alpha 通道且 RGB 全黑,用 alpha 通道作为灰度图
- if template.shape[2] == 4:
- alpha = template[:, :, 3]
- rgb_sum = template[:, :, :3].sum()
- if rgb_sum == 0:
- tmpl_gray = alpha # 用 alpha 通道
- else:
- tmpl_gray = cv2.cvtColor(template[:, :, :3], cv2.COLOR_BGR2GRAY)
- else:
- tmpl_gray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
-
- best = None
-
- # 先尝试原始尺寸
- scales = [1.0] + list(np.linspace(0.6, 1.4, 17))
- for scale in scales:
- rw, rh = int(w * scale), int(h * scale)
- if rh < 5 or rw < 5:
- continue
- if rh > main_gray.shape[0] or rw > main_gray.shape[1]:
- continue
-
- resized_tmpl = cv2.resize(tmpl_gray, (rw, rh))
- res = cv2.matchTemplate(main_gray, resized_tmpl, cv2.TM_CCOEFF_NORMED)
- _, max_val, _, max_loc = cv2.minMaxLoc(res)
-
- if best is None or max_val > best["confidence"]:
- best = {
- "x": max_loc[0],
- "y": max_loc[1],
- "w": rw,
- "h": rh,
- "confidence": max_val,
- "scale": scale,
- "center_x": max_loc[0] + rw // 2,
- "center_y": max_loc[1] + rh // 2,
- }
-
- if best is None or best["confidence"] < threshold:
- return []
- return [best]
-
-
-def main():
- base_dir = os.path.join(os.path.dirname(__file__), "images")
- main_img_path = os.path.join(base_dir, "1.jpg")
- templates = ["2.png", "3.png", "4.png"]
-
- print(f"主图: {main_img_path}\n")
-
- all_results = {}
- for tmpl_name in templates:
- tmpl_path = os.path.join(base_dir, tmpl_name)
- matches = find_template_in_image(main_img_path, tmpl_path, threshold=0.5)
- all_results[tmpl_name] = matches
-
- if matches:
- m = matches[0]
- print(f"[{tmpl_name}] 找到匹配:")
- print(f" 位置: ({m['x']}, {m['y']})")
- print(f" 中心点: ({m['center_x']}, {m['center_y']})")
- print(f" 尺寸: {m['w']}x{m['h']}")
- print(f" 置信度: {m['confidence']:.4f}")
- print(f" 缩放比例: {m['scale']:.2f}")
- else:
- print(f"[{tmpl_name}] 未找到匹配(置信度不足)")
- print()
-
- # 可视化结果,保存标注图
- main_img = cv2.imread(main_img_path)
- colors = [(0, 0, 255), (0, 255, 0), (255, 0, 0)] # 红、绿、蓝
- for i, tmpl_name in enumerate(templates):
- matches = all_results.get(tmpl_name, [])
- for m in matches:
- x, y, w, h = m["x"], m["y"], m["w"], m["h"]
- color = colors[i % len(colors)]
- cv2.rectangle(main_img, (x, y), (x + w, y + h), color, 2)
- cv2.putText(main_img, tmpl_name, (x, y - 5),
- cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2)
- # 画中心点
- cx, cy = m["center_x"], m["center_y"]
- cv2.circle(main_img, (cx, cy), 5, color, -1)
-
- output_path = os.path.join(base_dir, "result.jpg")
- cv2.imwrite(output_path, main_img)
- print(f"标注结果已保存到: {output_path}")
-
- # 打印点击坐标汇总(用于自动化点击)
- print("\n=== 点击坐标汇总 ===")
- for tmpl_name in templates:
- matches = all_results.get(tmpl_name, [])
- if matches:
- m = matches[0]
- print(f"{tmpl_name}: 点击 ({m['center_x']}, {m['center_y']})")
- else:
- print(f"{tmpl_name}: 未找到")
-
-
-if __name__ == "__main__":
- main()
diff --git a/gmail_reader.py b/gmail_reader.py
deleted file mode 100644
index e4eff0c..0000000
--- a/gmail_reader.py
+++ /dev/null
@@ -1,208 +0,0 @@
-"""
-Gmail API 邮件读取工具
-使用前准备:
-1. 访问 https://console.cloud.google.com/ 创建项目
-2. 启用 Gmail API
-3. 创建 OAuth 2.0 凭据(桌面应用类型),下载 credentials.json 放到本目录
-4. 首次运行会弹出浏览器授权,授权后自动生成 token.json
-"""
-
-import os
-import base64
-import json
-from datetime import datetime
-from google.auth.transport.requests import Request
-from google.oauth2.credentials import Credentials
-from google_auth_oauthlib.flow import InstalledAppFlow
-from googleapiclient.discovery import build
-from email.utils import parsedate_to_datetime
-
-# 只读权限
-SCOPES = ['https://www.googleapis.com/auth/gmail.readonly']
-
-# 凭据文件路径(和脚本同目录)
-BASE_DIR = os.path.dirname(os.path.abspath(__file__))
-CREDENTIALS_FILE = os.path.join(BASE_DIR, 'credentials.json')
-TOKEN_FILE = os.path.join(BASE_DIR, 'token.json')
-
-
-def get_service():
- """获取 Gmail API 服务实例"""
- creds = None
-
- # 尝试加载已有 token
- if os.path.exists(TOKEN_FILE):
- creds = Credentials.from_authorized_user_file(TOKEN_FILE, SCOPES)
-
- # token 无效或过期,重新授权
- if not creds or not creds.valid:
- if creds and creds.expired and creds.refresh_token:
- creds.refresh(Request())
- else:
- if not os.path.exists(CREDENTIALS_FILE):
- print(f"❌ 找不到 {CREDENTIALS_FILE}")
- print("请从 Google Cloud Console 下载 OAuth 凭据文件,命名为 credentials.json 放到本目录")
- return None
- flow = InstalledAppFlow.from_client_secrets_file(CREDENTIALS_FILE, SCOPES)
- creds = flow.run_local_server(port=0)
-
- # 保存 token 供下次使用
- with open(TOKEN_FILE, 'w') as f:
- f.write(creds.to_json())
-
- return build('gmail', 'v1', credentials=creds)
-
-
-def decode_body(payload):
- """递归解析邮件正文(优先纯文本)"""
- # 直接有 body data
- if 'body' in payload and payload['body'].get('data'):
- return base64.urlsafe_b64decode(payload['body']['data']).decode('utf-8', errors='ignore')
-
- # 多部分邮件,递归查找
- if 'parts' in payload:
- # 优先找 text/plain
- for part in payload['parts']:
- if part.get('mimeType') == 'text/plain':
- data = part['body'].get('data', '')
- if data:
- return base64.urlsafe_b64decode(data).decode('utf-8', errors='ignore')
-
- # 没有纯文本,找 text/html
- for part in payload['parts']:
- if part.get('mimeType') == 'text/html':
- data = part['body'].get('data', '')
- if data:
- return base64.urlsafe_b64decode(data).decode('utf-8', errors='ignore')
-
- # 递归子部分
- for part in payload['parts']:
- result = decode_body(part)
- if result:
- return result
-
- return None
-
-
-def get_header(headers, name):
- """从 headers 列表中取指定字段"""
- for h in headers:
- if h['name'].lower() == name.lower():
- return h['value']
- return ''
-
-
-def list_emails(service, query='', label_ids=None, max_results=10):
- """
- 列出邮件
- :param query: Gmail 搜索语法,如 'from:xxx@gmail.com' 'subject:报告' 'is:unread'
- :param label_ids: 标签过滤,如 ['INBOX'], ['UNREAD']
- :param max_results: 最多返回条数
- """
- params = {'userId': 'me', 'maxResults': max_results}
- if query:
- params['q'] = query
- if label_ids:
- params['labelIds'] = label_ids
-
- results = service.users().messages().list(**params).execute()
- return results.get('messages', [])
-
-
-def read_email(service, msg_id):
- """读取单封邮件详情"""
- msg = service.users().messages().get(userId='me', id=msg_id, format='full').execute()
- headers = msg['payload']['headers']
-
- subject = get_header(headers, 'Subject') or '(无主题)'
- sender = get_header(headers, 'From')
- to = get_header(headers, 'To')
- date_str = get_header(headers, 'Date')
- body = decode_body(msg['payload']) or '(无正文)'
-
- # 解析日期
- try:
- date = parsedate_to_datetime(date_str)
- date_str = date.strftime('%Y-%m-%d %H:%M:%S')
- except Exception:
- pass
-
- return {
- 'id': msg_id,
- 'subject': subject,
- 'from': sender,
- 'to': to,
- 'date': date_str,
- 'body': body,
- 'labels': msg.get('labelIds', []),
- 'snippet': msg.get('snippet', ''),
- }
-
-
-def get_attachments(service, msg_id, save_dir=None):
- """下载邮件附件"""
- msg = service.users().messages().get(userId='me', id=msg_id, format='full').execute()
- attachments = []
-
- if save_dir is None:
- save_dir = os.path.join(BASE_DIR, 'attachments')
-
- def _find_attachments(payload):
- if 'parts' in payload:
- for part in payload['parts']:
- filename = part.get('filename', '')
- if filename and part['body'].get('attachmentId'):
- att = service.users().messages().attachments().get(
- userId='me', messageId=msg_id, id=part['body']['attachmentId']
- ).execute()
- data = base64.urlsafe_b64decode(att['data'])
-
- os.makedirs(save_dir, exist_ok=True)
- filepath = os.path.join(save_dir, filename)
- with open(filepath, 'wb') as f:
- f.write(data)
-
- attachments.append({'filename': filename, 'path': filepath, 'size': len(data)})
- print(f" 📎 已保存附件: {filename} ({len(data)} bytes)")
-
- # 递归
- _find_attachments(part)
-
- _find_attachments(msg['payload'])
- return attachments
-
-
-# ============ 使用示例 ============
-
-if __name__ == '__main__':
- service = get_service()
- if not service:
- exit(1)
-
- print("=" * 60)
- print("📬 Gmail 邮件读取")
- print("=" * 60)
-
- # --- 示例1: 读取收件箱最近 5 封邮件 ---
- print("\n📥 收件箱最近 5 封邮件:\n")
- messages = list_emails(service, label_ids=['INBOX'], max_results=5)
-
- for m in messages:
- email_data = read_email(service, m['id'])
- print(f"📧 主题: {email_data['subject']}")
- print(f" 发件人: {email_data['from']}")
- print(f" 日期: {email_data['date']}")
- print(f" 摘要: {email_data['snippet'][:80]}...")
- print()
-
- # --- 示例2: 搜索特定邮件(取消注释使用)---
- # messages = list_emails(service, query='subject:报告 is:unread', max_results=5)
-
- # --- 示例3: 读取完整正文 ---
- # if messages:
- # email_data = read_email(service, messages[0]['id'])
- # print(f"\n完整正文:\n{email_data['body']}")
-
- # --- 示例4: 下载附件 ---
- # if messages:
- # get_attachments(service, messages[0]['id'])
diff --git a/images/1.jpg b/images/1.jpg
deleted file mode 100644
index b61bdcf..0000000
Binary files a/images/1.jpg and /dev/null differ
diff --git a/images/2.png b/images/2.png
deleted file mode 100644
index 055b62a..0000000
Binary files a/images/2.png and /dev/null differ
diff --git a/images/3.png b/images/3.png
deleted file mode 100644
index e4d079d..0000000
Binary files a/images/3.png and /dev/null differ
diff --git a/images/4.png b/images/4.png
deleted file mode 100644
index c7c9823..0000000
Binary files a/images/4.png and /dev/null differ
diff --git a/images/result_clip.jpg b/images/result_clip.jpg
deleted file mode 100644
index 88aef20..0000000
Binary files a/images/result_clip.jpg and /dev/null differ
diff --git a/images/result_vl.jpg b/images/result_vl.jpg
deleted file mode 100644
index 1b9b0a9..0000000
Binary files a/images/result_vl.jpg and /dev/null differ
diff --git a/match_alpha.py b/match_alpha.py
deleted file mode 100644
index 017f9f2..0000000
--- a/match_alpha.py
+++ /dev/null
@@ -1,65 +0,0 @@
-import cv2
-import numpy as np
-
-base = 'c:/Users/27942/Desktop/codes/codex_jxs_code/images/'
-main_img = cv2.imread(base + '1.jpg')
-main_gray = cv2.cvtColor(main_img, cv2.COLOR_BGR2GRAY)
-
-def match_template_alpha(main_gray, alpha, name):
- h, w = alpha.shape[:2]
- best = None
-
- # 策略1: 直接用alpha通道匹配灰度图
- # 策略2: 用alpha做mask,只比较非透明区域
- # 策略3: 对alpha二值化后匹配
-
- _, alpha_bin = cv2.threshold(alpha, 10, 255, cv2.THRESH_BINARY)
-
- scales = [1.0] + list(np.linspace(0.65, 1.35, 29))
- for scale in scales:
- rw, rh = int(w * scale), int(h * scale)
- if rh < 10 or rw < 10:
- continue
- if rh > main_gray.shape[0] or rw > main_gray.shape[1]:
- continue
-
- resized_alpha = cv2.resize(alpha, (rw, rh))
- resized_bin = cv2.resize(alpha_bin, (rw, rh))
- _, resized_mask = cv2.threshold(resized_bin, 10, 255, cv2.THRESH_BINARY)
-
- # 用mask匹配(只看非透明区域)
- res = cv2.matchTemplate(main_gray, resized_alpha, cv2.TM_CCOEFF_NORMED, mask=resized_mask)
- _, max_val, _, max_loc = cv2.minMaxLoc(res)
-
- if best is None or max_val > best['conf']:
- best = {
- 'x': max_loc[0], 'y': max_loc[1],
- 'w': rw, 'h': rh,
- 'conf': max_val, 'scale': scale,
- 'cx': max_loc[0] + rw // 2,
- 'cy': max_loc[1] + rh // 2,
- }
-
- return best
-
-results = {}
-for name in ['2.png', '3.png', '4.png']:
- template = cv2.imread(base + name, cv2.IMREAD_UNCHANGED)
- alpha = template[:, :, 3]
- best = match_template_alpha(main_gray, alpha, name)
- results[name] = best
- x, y, cx, cy = best['x'], best['y'], best['cx'], best['cy']
- conf, scale = best['conf'], best['scale']
- print(name + ': pos=(' + str(x) + ',' + str(y) + ') center=(' + str(cx) + ',' + str(cy) + ') conf=' + str(round(conf, 4)) + ' scale=' + str(round(scale, 2)))
-
-# 可视化
-colors = [(0, 0, 255), (0, 255, 0), (255, 0, 0)]
-vis = main_img.copy()
-for i, name in enumerate(['2.png', '3.png', '4.png']):
- m = results[name]
- cv2.rectangle(vis, (m['x'], m['y']), (m['x'] + m['w'], m['y'] + m['h']), colors[i], 2)
- cv2.putText(vis, name, (m['x'], m['y'] - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, colors[i], 1)
- cv2.circle(vis, (m['cx'], m['cy']), 5, colors[i], -1)
-
-cv2.imwrite(base + 'result.jpg', vis)
-print('result saved to images/result.jpg')
diff --git a/models/database.db b/models/database.db
index bdc38fb..4796fd1 100644
Binary files a/models/database.db and b/models/database.db differ