public PCRUnit GetBattleTeamInfoByIndex(Mat viewportMat, RECT viewportRect, int index)
        {
            var key              = $"Battle_Team_Slot_{index}";
            var rectRate         = GetMatchSourceRectRate(key);
            var threshold        = GetMatchTemplateThreshold("Battle_Team_Slot");
            var matchSourceMat   = viewportMat.GetChildMatByRectRate(rectRate);
            var unitIDs          = PCRUnit.GetAllUnitIDs();
            var templateWidth    = configMgr.UnitAvatarTemplateSize.Width;
            var getByAvatarLevel = new Func <string, PCRAvatarLevel, PCRUnit>((unitID, avatarLevel) =>
            {
                if (unitID == PCRUnit.UnknownUnitID)
                {
                    return(null);
                }
                Mat avatarPartial;
                lock (getUnitAvatarPartialLock)
                {
                    avatarPartial = GetUnitAvatarPartial(unitID, avatarLevel, templateWidth);
                }
                var matchRes = opencvTools.MatchImage(matchSourceMat, avatarPartial, threshold);
                if (matchRes.Success)
                {
                    return(PCRUnit.FromUnitID(unitID, avatarLevel.GetRequiredStars()));
                }
                else
                {
                    return(null);
                }
            });
            var getByAvatarLevelNoEx = new Func <string, PCRAvatarLevel, PCRUnit>((unitID, avatarLevel) =>
            {
                try { return(getByAvatarLevel(unitID, avatarLevel)); }
                catch { return(null); }
            });

            foreach (var unitID in unitIDs)
            {
                PCRUnit unit;
                unit = getByAvatarLevelNoEx(unitID, PCRAvatarLevel.Level3);
                if (unit != null)
                {
                    return(unit);
                }
                unit = getByAvatarLevelNoEx(unitID, PCRAvatarLevel.Level1);
                if (unit != null)
                {
                    return(unit);
                }
                unit = getByAvatarLevelNoEx(unitID, PCRAvatarLevel.Level6);
                if (unit != null)
                {
                    return(unit);
                }
            }
            return(null);
        }
        protected Mat GetUnitAvatarPartial(string unitID, PCRAvatarLevel avatarLevel, int templateWidth)
        {
            var key = $"{unitID}_{avatarLevel}_{templateWidth}";

            if (unitAvatarPartialDict.ContainsKey(key))
            {
                return(unitAvatarPartialDict[key]);
            }
            var unit          = PCRUnit.FromUnitID(unitID, avatarLevel.GetRequiredStars());
            var avatar        = unit.GetResizedAvatar(avatarLevel, templateWidth);
            var avatarPartial = avatar.GetChildMatByRectRate(unitAvatarPartialRectRate);

            unitAvatarPartialDict[key] = avatarPartial;
            return(avatarPartial);
        }