добавление нескольких значений растрового изображения для одного ключа в словаре с C # - PullRequest
4 голосов
/ 01 апреля 2012

У меня был словарь для хранения изображений шаблонов для целей распознавания текста. Я извлек эти растровые изображения из словаря и сравнил их с обрезанными по изображению, если они совпадают => захватил ключ (часть OCR выполнена).

Проблема возникает здесь. Один ключ должен быть представлен несколькими разными растровыми изображениями (то есть значениями). Как добавить несколько словарей в словарь для представления одного и того же ключа?

вот как я использовал словарь:

    Dictionary<string, Bitmap> lookup = new Dictionary<string, Bitmap>();
    lookup.Add("A", new Bitmap(@"C:\08\letters\1\a1.bmp", true));
    lookup.Add("A", new Bitmap(@"C:\08\letters\1\a2.bmp", true)); // Error will be here, because key A already exists for one Bitmap value.
    lookup.Add("a", new Bitmap(@"C:\08\letters\1\aa1.bmp", true));
    lookup.Add("B", new Bitmap(@"C:\08\letters\1\b1.bmp", true));

Теперь, чтобы получить изображения и значения, я сделал следующее:

var target = lookup.ToList();
bitmap b1 = target[j].Value; //grab value
//if value = cropped bitmap => proceed
string key = target[j].Key; //grab key

Как этот процесс изменится в соответствии с вашим решением?

P.s. Я слышал о «System.Linq.Lookup (Of TKey, TElement)», но никогда не использовал его раньше. Поможет ли мне этот «поиск» решить мою проблему или это совершенно другой инструмент? Google тоже не знает об этом, поэтому пример приветствуется

обратите внимание, что я загружаю словарь только один раз, при запуске программы, поэтому не имеет значения, насколько быстро происходит добавление. Lookup, с другой стороны, это то, что беспокоит меня больше всего. У меня есть 120 элементов в двух из моих словарей, и согласно этой статье http://www.dotnetperls.com/dictionary-time - Поиск в списке намного медленнее, чем в словаре ..

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

Ответы [ 3 ]

2 голосов
/ 01 апреля 2012

Поиск . В основном это словарь Ключ к списку значений, а не ключ к значению.

lookup.Add("a", "123"); // creates 'a' key and adds '123' to it
lookup.Add("a", "456"); // adds '456' to existing 'a' key
lookup.Add("b", "000"); // creates 'b' key and adds '000' to it
0 голосов
/ 01 апреля 2012

Во-первых, отличается от «множественных bmp-s» до «, представляющих ключ », или «один ключ», связанный (сопоставленный) с несколькими «значениями», - это то, что правильно предположил Йори. .
Так что, если вы хотите, чтобы к одному ключу было привязано больше значений - тогда вы можете использовать что-то вроде Dictionary<TKey, IList<TValue>> - где TKey и TValue - это нужные вам типы.
Но это не решает индексацию и запрос данных.
Это предполагает, что ваш «ключ» - это просто «А» в вашем случае - что не ясно, что это такое.
Так что в этом случае вы используете «словарь» для чего-то, что не должно использоваться. Словарь - это структура хеширования (в основном индексирует все свои записи в сегменты и т. Д.), Которая служит для ускорения процесса запросов и определения правильного значения.
Как я вижу в вашем случае, «ключом» является / является «набор растровых изображений», который как бы представляет «подпись» изображения с распознаванием OCR , если я прав? много в OCR, но я думаю, здесь.
Это немного усложняет, вам нужно создать «составной» ключ вида .
«Ключ», а не «значение» (или список значений) был бы растровыми изображениями (при условии, что их можно сделать сопоставимыми и равными или неравными, также существует проблема того, как вы сравниваете несколько значений с несколькими значениями и т. Д.). ).
Если это обычно так (но для более простых случаев, чем у вас), вы должны создать собственный класс и сделать так, чтобы этот класс имел переопределение GetHashCode () Equals (или IEqualityComparer) и т. Д., Чтобы его можно было использовать в качестве ключа в словарях. И затем вы используете это в качестве ключа.
Опять же, в вашем случае я думаю, что это немного растянуто (в некотором смысле, это нелегко реализовать).
По сути, вам нужно думать о «запросе» данных, а не о хранении. Каковы настоящие «ключи» для вашей системы. Если это растровое изображение, оно всегда одно и то же (или, если не так, как вы сравниваете с сигнатурой bmp), то вместо этого вы можете сохранить некоторый хэш-код bmp и использовать его в качестве ключа - и сравнить его вместо bmps.
то есть вам нужно думать о таких вещах - и тогда решение, как правило, будет очевидным, что вам нужно использовать.
Я бы не рекомендовал список , так как это выбор для бедных людей - если у вас не может быть только пара, так что легко пройти через это вручную, почему-то я не думаю, что это так в вашем случае.
Если вам нужен какой-то способ «индексации» по какому-либо ключу или ключам - тогда это, как правило, словарь (или словарь задействован тем или иным образом), но у вас может быть много «словарей» - или комбинаций. Также вы можете иметь «много типов ключей» и значений и т. Д.
Вы должны предоставить нам некоторые данные для этого.
надеюсь, это поможет
РЕДАКТИРОВАТЬ: И, наконец, - получить правильный 'хэш-код' также непросто - как с вашей пользовательской структурой, сравнивая, это то, что вам нужно решить самостоятельно - так что сводится к какой у вас ключ - и что представляет собой «ключ» (в каком свойстве значение лучше всего описывает его и делает его уникальным, что трудно сделать для изображения / BMP?), распределение хеш-значений и т. д.

0 голосов
/ 01 апреля 2012

Нельзя добавить элемент в dictionary с помощью того же ключа. Я думаю, что вы используете неправильную структуру данных. Я полагаю, вам, возможно, придется использовать list<> вместо этого. Как это:

var lookup=new List<KeyValuePair<string,Bitmap>>();
lookup.Add(new KeyValuePair<string,Bitmap>("A", new Bitmap(@"C:\08\letters\1\a1.bmp", true)));
lookup.Add(new KeyValuePair<string,Bitmap>("A", new Bitmap(@"C:\08\letters\1\a2.bmp", true)));
lookup.Add(new KeyValuePair<string,Bitmap>("a", new Bitmap(@"C:\08\letters\1\aa1.bmp", true)));
lookup.Add(new KeyValuePair<string,Bitmap>("B", new Bitmap(@"C:\08\letters\1\b1.bmp", true)));

Вы можете сделать это вместо этого. Без выполнения ToList():

bitmap b1 = target[j].Value; //grab value
string key = target[j].Key; //grab key

Редактировать

Но если вы делаете ToList() на Dictionary, тогда вы упускаете момент, когда на первом месте стоит Dictionary. Потому что тогда вы все равно получаете доступ к Dictionary пути list. Я также вижу проблему при выполнении ToList() на Dictionary, потому что сортировка в Dictionary выполняется не так, как вы их вставляете, а по хешу. Это означает, что вы не можете быть уверены, что индекс 1 является индексом 1. Вы также должны учитывать, что операция add на Dictionary не так эффективна, как add на List. Бог вещей с помощью словаря в том, что поиск быстрый. Но это вы не используете с вашим текущим решением.

Так что я вижу два пути. Приведенный выше или убедитесь, что ключи уникальны, и найдите его с помощью поиска в Dictionary. Как это:

Dictionary<string, Bitmap> lookup = new Dictionary<string, Bitmap>();
lookup.Add("A", new Bitmap(@"C:\08\letters\1\a1.bmp", true));
lookup.Add("B", new Bitmap(@"C:\08\letters\1\a2.bmp", true));
lookup.Add("C", new Bitmap(@"C:\08\letters\1\aa1.bmp", true));
lookup.Add("D", new Bitmap(@"C:\08\letters\1\b1.bmp", true));

Тогда вы можете получить Bitmap вот так:

Bitmap bm;
if(lookup.TryGetValue("A",out bm))
{
    //Do something
}

Или, если вы знаете, что ключ присутствует в Dictionary, вы можете сделать так:

Bitmap bm;
bm= lookup["A"];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...