Как отсортировать место добавления объекта на основе его атрибута - PullRequest
0 голосов
/ 11 февраля 2020

Мне интересно, может ли кто-нибудь объяснить метод, который добавляет объекты с одинаковым значением атрибута в отдельные списки.

В этом случае список кандидатов не может содержать кандидатов с одинаковым номером кадра.

Я ищу способ реализовать это в методе Add () для CandidateList.

Как этого добиться?

public class CandidateList
{
    public CandidateList()
    {
        _Candidates1 = new List<Candidate>();
        _Candidates2 = new List<Candidate>();
        _Candidates3 = new List<Candidate>();
        _Candidates4 = new List<Candidate>();
    }

    public void Add(Candidate candidate)
    {
        // Check candidate frame number
        // How to decide which list candidate should be added to?
        // If candidate.frameNumber matches an element in Candidates1[candidate.framenumber]
        // add this candidate to Candidates2, and so on..



    }
}

public class Candidate
{
    //Attributes shown in constructor.

    public Candidate(VectorOfPoint contour, int frameNumber, double contourSize, Point location)
    {
        Contour = contour;
        FrameNumber = frameNumber;
        ContourSize = contourSize;
        Location = location;
        Location_x = Location.X;
        Location_y = Location.Y;
    }
}

_vc = new VideoCapture(someURLorFilePath);
_candidateList = new CandidateList();
_vc.ImageGrabbed += ProcessFrame;

public void ProcessFrame(object sender, EventArgs e)
{
    Mat _frame = new Mat(); 
    // read frame.. + other operations to get desired data.

    Mat _contourOutput = _frame.Clone();
    VectorOfVectorOfPoint _contours = new VectorOfVectorOfPoint();

    CvInvoke.FindContours(_contourOutput, _contours, new Mat(), RetrType.External, ChainApproxMethod.ChainApproxSimple);

    // If there are any contours
    if (_contours.Size > 0)
    {
        // Iterate through contours
        for (var i = 0; i < _contours.Size; i++)
        {
            // Find contour area of each contour (VectorOfPoint)
            double _contourArea = CvInvoke.ContourArea(_contours[i]);

            // Find centre of contour
            Moments M = CvInvoke.Moments(_contours[i]);

            Point _contourCentre = new Point(Convert.ToInt16(M.M10 / M.M00), Convert.ToInt16(M.M01 / M.M00));

            //  Create a candidate based on frame number, contourSize and location
            Candidate _candidate = new Candidate(_contours[i], _currentFrameNo, _contourArea, _contourCentre);
            _candidateList.Add(_candidate)                     

        }
    }

    _currentFrameNo ++
}







Ответы [ 3 ]

3 голосов
/ 11 февраля 2020

Я бы рекомендовал использовать Dictionary<int, List<Candidate>> вместо нескольких списков.

Ваш CandidateList может выглядеть так:

public class CandidateList
{
    private Dictionary<int, List<Candidate>> _candidatesByFrameNumber;

    public CandidateList()
    {
        _candidatesByFrameNumber = new Dictionary<int, List<Candidate>>();
    }

    public void Add(Candidate candidate)
    {
        if (!_candidatesByFrameNumber.TryGetValue(candidate.FrameNumber, out var lst))
        {
            lst = new List<Candidate>();
            _candidatesByFrameNumber.Add(candidate.FrameNumber, lst);
        }

        lst.Add(candidate);
    }
}
1 голос
/ 11 февраля 2020

Я думаю, вам не нужно несколько списков вообще. Вы усложняете проблему. все, что вам нужно, это всего лишь один простой список для хранения вашего Candidates и получения запроса из списка по frameNumber или другим полям.

public class CandidateList
{
    public List<Candidate> _CandidatesList;

    public CandidateList()
    {
        _CandidatesList = new List<Candidate>();
    }

    // actually you need this method anymore
    // you can use _CandidatesList.Add() instead.
    public void Add(Candidate candidate)
    {
        _CandidatesList.Add(candidate);
    }


    public IEnumerable<Candidate> GetCandidateByFrameNumber(int frameNumber)
    {
        // this is how you can query the data depending your needs and get seprated results.
        return _CandidatesList.Where(q => q.FrameNumber == frameNumber );
    }   
}

0 голосов
/ 11 февраля 2020
public class CandidateList
{

 private List<Dictionary<Int, Candidate>> candidatList;

 public CandidateList()
 {
    candidatList= new List<Dictionary<int, Candidate>>();
 }

 public void Add(Candidate candidate)
 {

    Var element = New <Dictionary<candidate.FrameNumber, Candidate>();
    candidatList.Add(element);
 }

 public List<Candidate> GetList(int frameNum)
 {
    List<Candidate> lst = New List<Candidate>()
    foreach (int key in CandidateList.Keys)
    {
        if (key == frameNum)
        {
          lst.Add(CandidateList[key])
        }
    }
    return lst; 
 }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...