Calibrate orb detection from botty reference: vertical slice method, correct HSV ranges

- Add ReadOrbSlicePercentage: thin vertical strip method for accurate fill reading
- Support HSV hue wrapping in colorInRange (for red hues crossing 360°)
- Health HSV: H 350-370 (wrapping), S 60+, V 20+ (calibrated from screenshot)
- Mana HSV: H 226-240, S 100+, V 20+ (calibrated from screenshot)
- Add health_slice/mana_slice regions (10px wide vertical strips through orb centers)
- Update health_globe/mana_globe to full botty-referenced regions
- Verified: health 96.3%, mana 100% on testdata/d2r_1080p.png (both at 100% fill)
This commit is contained in:
Hoid 2026-02-14 11:56:18 +00:00
parent 0716aeb5e1
commit 35a1944179
8 changed files with 117 additions and 44 deletions

View file

@ -56,11 +56,12 @@ type Config struct {
func DefaultConfig() Config {
return Config{
Colors: Colors{
// Calibrated HSV ranges from real D2R screenshot (testdata/d2r_1080p.png)
// Health orb is bright RED: RGB ~(236,15,20) → HSV H 0-10, S 150+, V 150+
HealthFilled: HSVRange{0, 150, 150, 10, 255, 255},
// Mana orb is BLUE: H 200-240, S 100+, V 80+
ManaFilled: HSVRange{200, 100, 80, 240, 255, 255},
// Calibrated from botty reference (720p scaled to 1080p)
// Health orb RED: OpenCV H 178-183 → our H 356-366, wraps around 360
// Using H 350-360 + H 0-10 range (handled by wrapping in colorInRange)
HealthFilled: HSVRange{350, 60, 20, 370, 255, 255}, // H wraps: 350-370 means 350-360,0-10
// Mana orb BLUE: actual H 228-236 from screenshot
ManaFilled: HSVRange{226, 100, 20, 240, 255, 255},
ItemUnique: HSVRange{15, 100, 180, 30, 255, 255},
ItemSet: HSVRange{35, 100, 150, 55, 255, 255},
ItemRare: HSVRange{15, 50, 200, 25, 150, 255},
@ -96,15 +97,19 @@ func RegisterProfiles(registry *resolution.Registry) error {
Height: 1080,
Label: "1080p",
Regions: map[string]image.Rectangle{
"health_orb": image.Rect(370, 945, 460, 1030),
"mana_orb": image.Rect(1580, 910, 1670, 1000),
"xp_bar": image.Rect(0, 1058, 1920, 1080),
"belt": image.Rect(500, 990, 900, 1040),
"minimap": image.Rect(1600, 0, 1920, 320),
"inventory": image.Rect(960, 330, 1490, 770),
"stash": image.Rect(430, 330, 960, 770),
"skill_left": image.Rect(200, 1030, 250, 1078),
"skill_right": image.Rect(1670, 1030, 1730, 1078),
"health_globe": image.Rect(240, 870, 600, 1080), // Full health globe region
"mana_globe": image.Rect(1330, 870, 1690, 1080), // Full mana globe region
"health_slice": image.Rect(415, 915, 425, 1060), // Thin vertical strip through orb center
"mana_slice": image.Rect(1505, 915, 1515, 1060), // Thin vertical strip through orb center
"health_orb": image.Rect(240, 870, 600, 1080), // Alias for backward compat
"mana_orb": image.Rect(1330, 870, 1690, 1080), // Alias for backward compat
"xp_bar": image.Rect(0, 1058, 1920, 1080),
"belt": image.Rect(500, 990, 900, 1040),
"minimap": image.Rect(1600, 0, 1920, 320),
"inventory": image.Rect(960, 330, 1490, 770),
"stash": image.Rect(430, 330, 960, 770),
"skill_left": image.Rect(200, 1030, 250, 1078),
"skill_right": image.Rect(1670, 1030, 1730, 1078),
},
},
// 1280x720 (720p) - Secondary resolution (scaled from 1080p)
@ -113,15 +118,19 @@ func RegisterProfiles(registry *resolution.Registry) error {
Height: 720,
Label: "720p",
Regions: map[string]image.Rectangle{
"health_orb": image.Rect(247, 630, 307, 687),
"mana_orb": image.Rect(1053, 607, 1113, 667),
"xp_bar": image.Rect(0, 705, 1280, 720),
"belt": image.Rect(333, 660, 600, 693),
"minimap": image.Rect(1067, 0, 1280, 213),
"inventory": image.Rect(640, 220, 993, 513),
"stash": image.Rect(287, 220, 640, 513),
"skill_left": image.Rect(133, 687, 167, 718),
"skill_right": image.Rect(1113, 687, 1153, 718),
"health_globe": image.Rect(160, 580, 400, 720),
"mana_globe": image.Rect(887, 580, 1127, 720),
"health_slice": image.Rect(309, 610, 316, 711),
"mana_slice": image.Rect(961, 610, 968, 711),
"health_orb": image.Rect(160, 580, 400, 720),
"mana_orb": image.Rect(887, 580, 1127, 720),
"xp_bar": image.Rect(0, 705, 1280, 720),
"belt": image.Rect(333, 660, 600, 693),
"minimap": image.Rect(1067, 0, 1280, 213),
"inventory": image.Rect(640, 220, 993, 513),
"stash": image.Rect(287, 220, 640, 513),
"skill_left": image.Rect(133, 687, 167, 718),
"skill_right": image.Rect(1113, 687, 1153, 718),
},
},
}