Skip to content

fix(scan): recognize current inventory icons - #24

Closed
DysektAI wants to merge 1 commit into
masterfrom
fix/inventory-recognition
Closed

fix(scan): recognize current inventory icons#24
DysektAI wants to merge 1 commit into
masterfrom
fix/inventory-recognition

Conversation

@DysektAI

@DysektAI DysektAI commented Jul 27, 2026

Copy link
Copy Markdown
Member

What changed

  • detect current one-pixel inventory cell borders with a contour fallback while retaining the existing fast grid parser
  • reject fully transparent catalog icons before they become background-only templates
  • include source size and timestamp in generated-icon cache identity so replaced catalog images invalidate old templates
  • verify low-confidence template matches with a unique exact short-name OCR result when traineddata is available
  • add synthetic regression coverage for one-pixel adjacent cells, transparent icons, cache invalidation, and OCR normalization/uniqueness

Why

The current game UI can render one-pixel inventory borders that the legacy erosion-based grid walker loses. Transparent placeholder PNGs can also become misleading templates, while FIR/wishlist decoration can dominate low-confidence whole-cell template scores.

This ports the validated recognition behavior from the experimental RatEye branch into RatScanner's authoritative in-tree src/ScanEngine architecture. It does not reintroduce a submodule.

Impact

Current inventory cells are localized again, stale generated templates are invalidated when their source changes, and low-confidence matches can be corrected only when OCR resolves one unique exact catalog short name. Missing OCR traineddata leaves template matching operational.

Validation

  • dotnet csharpier check .
  • Debug build — 0 warnings, 0 errors
  • Debug tests — 230 passed, 5 optional real-image harness tests skipped
  • Release build — 0 warnings, 0 errors
  • Release tests — 229 passed, 5 optional real-image harness tests skipped before the final cache regression was added

Accuracy-sensitive real-game smoke evidence originated from the controlled four-case replay used for the source fix; the copyrighted fixture corpus remains local and is not committed.


Summary by cubic

Restores reliable inventory icon detection in the current UI by handling 1‑px cell borders and preventing bad templates, with OCR-based verification for low-confidence matches and cache keys that track source changes. Current cells are found again and stale generated icons are replaced automatically.

  • Bug Fixes

    • Detect 1‑px inventory borders via a contour fallback while keeping the fast grid parser.
    • Reject fully transparent static icons before template generation.
    • Add source size and timestamp to generated-icon cache keys to invalidate when catalog images change.
  • New Features

    • Verify low-confidence template matches with a unique exact short-name OCR result when traineddata exists; otherwise template matching continues.
    • Add regression tests for 1‑px adjacent cells, transparent icons, cache invalidation, and OCR normalization.

Written for commit afd87f1. Summary will update on new commits.

Review in cubic

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: improving current inventory icon recognition.
Description check ✅ Passed The description matches the changeset and explains the inventory detection, OCR verification, and cache invalidation updates.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/inventory-recognition

Comment @coderabbitai help to get the list of available commands.

@codeant-ai

codeant-ai Bot commented Jul 27, 2026

Copy link
Copy Markdown

🏁 CodeAnt Quality Gate Results

Commit: afd87f1e
Scan Time: 2026-07-27 16:19:55 UTC

✅ Overall Status: PASSED

Quality Gate Details

Quality Gate Status Details
Secrets ✅ PASSED 0 secrets found
Duplicate Code ✅ PASSED 0.0% duplicated
SAST ✅ PASSED No security issues
Bugs ✅ PASSED Rating S: No bugs
IAC ✅ PASSED No IAC issues

View Full Results

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/ScanEngine/Processing/Icon.cs`:
- Around line 358-417: The VerifyLowConfidenceTemplateMatchWithOcr method must
contain exception handling around its OpenCV/Tesseract OCR operations so
failures do not escape Item, DetectionConfidence, or ItemPosition accessors.
Reuse the existing IsRecoverableIconLoadException policy and logging behavior
from IconManager, while preserving the finally block’s disposal of ocrIcon and
allowing successful OCR verification to remain unchanged.
- Around line 19-21: Unify OCR sanitization by extracting the existing regex
used in OCR() into the shared OcrShortNameSanitizer symbol, then reuse it in
both the full-OCR and verification paths. Remove the divergent Unicode-aware
pattern so both paths apply identical normalization rules.
- Around line 363-366: Extract the trained-data path construction and existence
check from the current low-confidence flow and GetTesseractEngine() into a
shared helper such as TryGetTrainedDataPath. Update both call sites to reuse
that helper, preserving the existing language-code resolution and early-return
behavior while eliminating duplicate path logic and File.Exists checks.
- Around line 404-410: When OCR verification replaces the low-confidence match
in the verification block, recompute or reset _itemPosition for the new
verifiedItem so ItemPosition no longer uses the discarded candidate’s position.
Update the same assignment section that sets _item, _itemExtraInfo,
_detectionConfidence, and _rotated, preserving the existing position calculation
behavior used elsewhere for verified items.

In `@src/ScanEngine/Processing/Inventory.cs`:
- Around line 258-297: The AddContourIconsFromNormalGrid method should add debug
visualization consistent with DetectInventoryGridNormal,
ParseInventoryGridHighlighted, and LocateIcon. Under Config.LogDebug, log the
contour source mask and relevant candidate or padded rectangles through the
existing Logger.LogDebugMat pattern, preserving the current detection behavior
and avoiding logging when debug mode is disabled.
- Around line 258-297: Extract the shared padding calculation currently
duplicated in AddContourIconsFromNormalGrid and TryAddIcon into a reusable
helper. Have both methods call that helper for the top-left and size
adjustments, preserving the existing padding behavior and ensuring future
heuristic changes apply consistently.
- Around line 264-267: Update the FindContoursAsArray call in the contour
processing flow to use RetrievalModes.External instead of RetrievalModes.List,
while preserving the existing ContourApproximationModes.ApproxSimple setting.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f4f25a23-858f-415f-994c-f371d31b80e6

📥 Commits

Reviewing files that changed from the base of the PR and between da0607f and afd87f1.

📒 Files selected for processing (6)
  • src/ScanEngine/IconManager.cs
  • src/ScanEngine/Processing/Icon.cs
  • src/ScanEngine/Processing/Inventory.cs
  • tests/RatScanner.Tests/OpenCvPipelineTests.cs
  • tests/RatScanner.Tests/PresentationServicesTests.cs
  • tests/RatScanner.Tests/RatEyeCacheTests.cs

Comment on lines +19 to +21
private const float OcrVerificationThreshold = 0.7f;
private static readonly Regex OcrShortNameSanitizer = new(@"[^\p{L}\p{N} \-.]");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Two divergent OCR sanitizer regexes.

OcrShortNameSanitizer ([^\p{L}\p{N} \-.], Unicode-aware) duplicates the intent of the existing ASCII-only regex in OCR() (line 345, "[^a-zA-Z0-9 -\\."]). Having two slightly different sanitization rules for OCR text risks inconsistent normalization between the full-OCR path and this new verification path. Consider reusing one shared sanitizer.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/ScanEngine/Processing/Icon.cs` around lines 19 - 21, Unify OCR
sanitization by extracting the existing regex used in OCR() into the shared
OcrShortNameSanitizer symbol, then reuse it in both the full-OCR and
verification paths. Remove the divergent Unicode-aware pattern so both paths
apply identical normalization rules.

Comment on lines +358 to +417
private void VerifyLowConfidenceTemplateMatchWithOcr()
{
if (_detectionConfidence >= OcrVerificationThreshold)
return;

var langCode = ProcessingConfig.Language.ToISO3Code();
var trainedDataPath = System.IO.Path.Combine(PathConfig.TrainedData, $"{langCode}.traineddata");
if (!System.IO.File.Exists(trainedDataPath))
return;

Bitmap ocrIcon = _icon.Rescale(ProcessingConfig.InverseScale * 2);
try
{
var titleHeight = Math.Min(
ocrIcon.Height,
(int)Math.Round(ProcessingConfig.BaseSlotSize * (40f / 63f))
);
var titleLeft = Math.Min(ocrIcon.Width - 1, (int)Math.Floor(ocrIcon.Width * 0.55f));
using var title = ocrIcon.Crop(titleLeft, 0, ocrIcon.Width - titleLeft, titleHeight);
using var titleMat = title.ToMat();
using var gray =
titleMat.Channels() == 1 ? titleMat.Clone() : titleMat.CvtColor(ColorConversionCodes.BGR2GRAY);
using var binary = gray.Threshold(110, 255, ThresholdTypes.Binary);
Cv2.BitwiseNot(binary, binary);
using var enlarged = binary.Resize(new OpenCvSharp.Size(), 3, 3, InterpolationFlags.Cubic);
using var filteredBitmap = enlarged.ToBitmap();
using var pix = PixConverter.ToPix(filteredBitmap);

string text;
var tesseractEngine = GetTesseractEngine();
lock (tesseractEngine)
{
using var result = tesseractEngine.Process(pix, PageSegMode.SingleLine);
text = result.GetText();
}

var slotSize = IconSlotSize();
var items = _config.RatStashDB.GetItems(item =>
{
var size = new Vector2(item.GetSlotSize());
return size == slotSize || size == slotSize.Flipped;
});
var verifiedItem = FindUniqueExactShortName(items, text);
if (verifiedItem == null)
return;

_item = verifiedItem;
_itemExtraInfo = null;
_detectionConfidence = 1;
_rotated = new Vector2(verifiedItem.GetSlotSize()) != slotSize;
Logger.LogDebug(
$"Verified low-confidence template match as '{verifiedItem.ShortName}' using icon title OCR."
);
}
finally
{
if (!ReferenceEquals(ocrIcon, _icon))
ocrIcon.Dispose();
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

No exception handling around the new OCR verification path.

Unlike icon loading in IconManager (which wraps OpenCV/Tesseract/IO failures via IsRecoverableIconLoadException), VerifyLowConfidenceTemplateMatchWithOcr has no try/catch. Previously, TemplateMatching mode had zero runtime dependency on Tesseract; now every low-confidence match opportunistically runs OCR, so any native/Tesseract failure (corrupt traineddata, native crash, malformed pix) will propagate unguarded out of Item/DetectionConfidence/ItemPosition getters and can crash a scan that previously never touched OCR.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/ScanEngine/Processing/Icon.cs` around lines 358 - 417, The
VerifyLowConfidenceTemplateMatchWithOcr method must contain exception handling
around its OpenCV/Tesseract OCR operations so failures do not escape Item,
DetectionConfidence, or ItemPosition accessors. Reuse the existing
IsRecoverableIconLoadException policy and logging behavior from IconManager,
while preserving the finally block’s disposal of ocrIcon and allowing successful
OCR verification to remain unchanged.

Comment on lines +363 to +366
var langCode = ProcessingConfig.Language.ToISO3Code();
var trainedDataPath = System.IO.Path.Combine(PathConfig.TrainedData, $"{langCode}.traineddata");
if (!System.IO.File.Exists(trainedDataPath))
return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated trained-data path resolution/existence check.

This re-derives and re-checks the trained-data path that GetTesseractEngine() (line ~483) already builds and checks independently, using a different construction strategy (Path.Combine here vs. manual "\\" concatenation there). Functionally equivalent on Windows, but it's duplicated logic and a duplicate File.Exists syscall on every low-confidence match; consider extracting a single helper (e.g. TryGetTrainedDataPath) used by both call sites.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/ScanEngine/Processing/Icon.cs` around lines 363 - 366, Extract the
trained-data path construction and existence check from the current
low-confidence flow and GetTesseractEngine() into a shared helper such as
TryGetTrainedDataPath. Update both call sites to reuse that helper, preserving
the existing language-code resolution and early-return behavior while
eliminating duplicate path logic and File.Exists checks.

Comment on lines +404 to +410
_item = verifiedItem;
_itemExtraInfo = null;
_detectionConfidence = 1;
_rotated = new Vector2(verifiedItem.GetSlotSize()) != slotSize;
Logger.LogDebug(
$"Verified low-confidence template match as '{verifiedItem.ShortName}' using icon title OCR."
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

_itemPosition goes stale when OCR overrides the item.

When OCR verification swaps in a different verifiedItem, _itemPosition still holds the position computed for the discarded, low-confidence template match — which was for a different (likely wrong) item entirely. _rotated is correctly recomputed for the new item, but the position isn't, so ItemPosition will report a misleading location tied to the wrong candidate's match.

🐛 Proposed fix
                 _item = verifiedItem;
                 _itemExtraInfo = null;
                 _detectionConfidence = 1;
+                _itemPosition = Vector2.Zero;
                 _rotated = new Vector2(verifiedItem.GetSlotSize()) != slotSize;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
_item = verifiedItem;
_itemExtraInfo = null;
_detectionConfidence = 1;
_rotated = new Vector2(verifiedItem.GetSlotSize()) != slotSize;
Logger.LogDebug(
$"Verified low-confidence template match as '{verifiedItem.ShortName}' using icon title OCR."
);
_item = verifiedItem;
_itemExtraInfo = null;
_detectionConfidence = 1;
_itemPosition = Vector2.Zero;
_rotated = new Vector2(verifiedItem.GetSlotSize()) != slotSize;
Logger.LogDebug(
$"Verified low-confidence template match as '{verifiedItem.ShortName}' using icon title OCR."
);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/ScanEngine/Processing/Icon.cs` around lines 404 - 410, When OCR
verification replaces the low-confidence match in the verification block,
recompute or reset _itemPosition for the new verifiedItem so ItemPosition no
longer uses the discarded candidate’s position. Update the same assignment
section that sets _item, _itemExtraInfo, _detectionConfidence, and _rotated,
preserving the existing position calculation behavior used elsewhere for
verified items.

Comment on lines +258 to +297
private void AddContourIconsFromNormalGrid()
{
if (_normalGridMask == null || _normalGridMask.Empty())
return;

using var contourSource = _normalGridMask.Clone();
var contours = contourSource.FindContoursAsArray(
RetrievalModes.List,
ContourApproximationModes.ApproxSimple
);
var scaledSlotSize = (int)ProcessingConfig.ScaledSlotSize;
var tolerance = Math.Max(3, (int)Math.Ceiling(scaledSlotSize * 0.08));
var imageBounds = new Rect(0, 0, _image.Width, _image.Height);

using var image = _image.ToBitmap();
foreach (var contour in contours)
{
var rect = Cv2.BoundingRect(contour);
if (
!IsSlotAlignedDimension(rect.Width, scaledSlotSize, tolerance)
|| !IsSlotAlignedDimension(rect.Height, scaledSlotSize, tolerance)
)
continue;

var scaledSlotSizeVec = new Vector2(scaledSlotSize, scaledSlotSize);
var topLeft = new Vector2(rect.Location) - scaledSlotSizeVec / 8;
var size = new Vector2(rect.Size) + scaledSlotSizeVec / 4;
var paddedRect = new Rect(topLeft, size).Intersect(imageBounds);
if (paddedRect.Width <= 0 || paddedRect.Height <= 0)
continue;

topLeft = new Vector2(paddedRect.Location);
size = new Vector2(paddedRect.Size);
if (_icons.Any(icon => icon.Position == topLeft && icon.Size == size))
continue;

var iconImage = image.Crop(topLeft.X, topLeft.Y, size.X, size.Y);
_icons.Add(new Icon(iconImage, topLeft, size, _config));
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add debug logging consistent with sibling detection methods.

Every other detection path in this class (DetectInventoryGridNormal, ParseInventoryGridHighlighted, LocateIcon) logs intermediate masks/candidate rectangles via Logger.LogDebugMat under Config.LogDebug. This new contour-fallback path adds no equivalent visualization, making it harder to diagnose accuracy issues (e.g., over/under-detection, alignment tolerance tuning) in the field. As per coding guidelines, "Log through existing engine logger patterns."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/ScanEngine/Processing/Inventory.cs` around lines 258 - 297, The
AddContourIconsFromNormalGrid method should add debug visualization consistent
with DetectInventoryGridNormal, ParseInventoryGridHighlighted, and LocateIcon.
Under Config.LogDebug, log the contour source mask and relevant candidate or
padded rectangles through the existing Logger.LogDebugMat pattern, preserving
the current detection behavior and avoiding logging when debug mode is disabled.

Source: Coding guidelines


📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Extract shared padding logic instead of duplicating TryAddIcon's formula.

The padding computation (topLeft -= scaledSlotSizeVec/8; size += scaledSlotSizeVec/4;) is copy-pasted verbatim from TryAddIcon (Lines 497-500). If the padding heuristic is ever tuned for one path, the other will silently diverge, causing inconsistent icon crop sizes between grid-detected and contour-detected icons.

♻️ Proposed extraction
+        private Rect PadIconRect(Rect rect, int scaledSlotSize)
+        {
+            var scaledSlotSizeVec = new Vector2(scaledSlotSize, scaledSlotSize);
+            var topLeft = new Vector2(rect.Location) - scaledSlotSizeVec / 8;
+            var size = new Vector2(rect.Size) + scaledSlotSizeVec / 4;
+            return new Rect(topLeft, size);
+        }

Then call it from both AddContourIconsFromNormalGrid and TryAddIcon.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/ScanEngine/Processing/Inventory.cs` around lines 258 - 297, Extract the
shared padding calculation currently duplicated in AddContourIconsFromNormalGrid
and TryAddIcon into a reusable helper. Have both methods call that helper for
the top-left and size adjustments, preserving the existing padding behavior and
ensuring future heuristic changes apply consistently.

Comment on lines +264 to +267
var contours = contourSource.FindContoursAsArray(
RetrievalModes.List,
ContourApproximationModes.ApproxSimple
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

OpenCvSharp FindContoursAsArray RetrievalModes.External behavior for closed shape with hole

💡 Result:

In OpenCvSharp, using the RetrievalModes.External mode with the FindContoursAsArray method retrieves only the "extreme outer" contours of shapes in a binary image [1][2][3]. When applied to a closed shape containing a hole, this mode will ignore the inner contour (the hole) entirely [4]. Only the outermost boundary of the object will be detected and returned as a contour [1][5][6]. This behavior is consistent across all implementations of OpenCV's findContours function because RetrievalModes.External is specifically designed to ignore nested structures and hierarchy [7][6][8]. The function also sets the hierarchy information for the detected outer contour to indicate it has no parent or child relationships (hierarchy[i][2] = hierarchy[i][7] = -1) [1][7][9].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant file and nearby logic.
FILE="src/ScanEngine/Processing/Inventory.cs"

echo "== Line count =="
wc -l "$FILE"

echo
echo "== Relevant range around contour handling =="
sed -n '180,320p' "$FILE"

echo
echo "== Search for contour / overlap / slot alignment helpers in the file =="
rg -n "FindContoursAsArray|RetrievalModes|IsSlotAlignedDimension|overlap|prun|contour|Bitmap|Icon" "$FILE"

Repository: tarkovtracker-org/RatScanner

Length of output: 8952


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="src/ScanEngine/Processing/Inventory.cs"
wc -l "$FILE"
sed -n '180,320p' "$FILE"
rg -n "FindContoursAsArray|RetrievalModes|IsSlotAlignedDimension|overlap|prun|contour|Bitmap|Icon" "$FILE"

Repository: tarkovtracker-org/RatScanner

Length of output: 8816


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="src/ScanEngine/Processing/Inventory.cs"
echo "== line count =="
wc -l "$FILE"
echo "== relevant range =="
sed -n '180,320p' "$FILE"
echo "== matches =="
rg -n "FindContoursAsArray|RetrievalModes|IsSlotAlignedDimension|overlap|prun|contour|Bitmap|Icon" "$FILE"

Repository: tarkovtracker-org/RatScanner

Length of output: 8868


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE="src/ScanEngine/Processing/Inventory.cs"
wc -l "$FILE"
sed -n '200,300p' "$FILE"
rg -n "FindContoursAsArray|RetrievalModes|IsSlotAlignedDimension|overlap|prun|contour|Bitmap|Icon" "$FILE"

Repository: tarkovtracker-org/RatScanner

Length of output: 6840


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "Trying to inspect repository files..."
git ls-files | rg '^src/ScanEngine/Processing/Inventory\.cs$|^src/ScanEngine/Processing/'

Repository: tarkovtracker-org/RatScanner

Length of output: 362


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="src/ScanEngine/Processing/Inventory.cs"

echo "== _normalGridMask references =="
rg -n "_normalGridMask|normalGridMask|FindContoursAsArray|RetrievalModes" "$FILE"

echo
echo "== section around mask construction / assignment =="
sed -n '80,180p' "$FILE"

echo
echo "== section around any other contour handling =="
sed -n '320,430p' "$FILE"

Repository: tarkovtracker-org/RatScanner

Length of output: 10135


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="src/ScanEngine/Processing/Inventory.cs"

echo "== lines 80-180 =="
sed -n '80,180p' "$FILE"

echo
echo "== lines 430-620 =="
sed -n '430,620p' "$FILE"

Repository: tarkovtracker-org/RatScanner

Length of output: 11580


Switch this contour retrieval to RetrievalModes.External
RetrievalModes.List returns both sides of the closed 1px slot border, so each cell produces duplicate contour crops that are only removed later. External keeps the outer contour and avoids that extra work.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/ScanEngine/Processing/Inventory.cs` around lines 264 - 267, Update the
FindContoursAsArray call in the contour processing flow to use
RetrievalModes.External instead of RetrievalModes.List, while preserving the
existing ContourApproximationModes.ApproxSimple setting.

@DysektAI

Copy link
Copy Markdown
Member Author

Closing as superseded by the standalone RatEye implementation merged in tarkovtracker-org/RatEye#1 and consumed by RatScanner PR #22. The inventory-recognition methods and regression coverage now live in the RatEye submodule, preserving the repository boundary.

@DysektAI DysektAI closed this Jul 29, 2026
@DysektAI
DysektAI deleted the fix/inventory-recognition branch July 29, 2026 06:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant