Перейти к содержимому
Compvision.ru

CornersKir

Пользователи
  • Количество публикаций

    11
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные пользователем CornersKir


  1. А что это за функция такая PRecord и где она валяется?

    Указатель на запись с требуемыми Вам данными. Для ранее приведённого примера с cvHoughLines2 и CV_HOUGH_STANDARD:

    Объявление:

      TLineRecord = record
    
    	Rho:   single;
    
    	Theta: single;
    
      end;
    
      PLineRecord = ^TLineRecord;
    Использование:
      var
    
      LineRecord: PLineRecord;
    
      Lines: pCvSeq;
    
      Rho: single;
    
      Theta: single;
    
      i: integer;
    
    
      for i := 0 to Lines.total - 1 do
    
      begin
    
    	LineRecord  :=  PLineRecord(cvGetSeqElem(Lines, i));
    
    
    	Rho   := LineRecord^.Rho;
    
    	Theta := LineRecord^.Theta;
    
    	// обработка
    
       end;


  2. Необходимо распознать текст на однотонном фоне (шрифт стандартный, например, Times New Roman) с определенной области изображения.

    За счет каких функций, решений это можно осуществить?

    Заранее спасибо.

    Можно использовать CuneiForm. Автоматизация через COM-сервер Puma. Лицензия тоже хорошая.


  3. 4. Строим горизонтальную и вертикальную проекцию каждого куска на исходном изображении (суммируем интенсивность каждого столбца и строки), белый фон будет давать всплески, иллюстрация - провалы.

    Реализовал указанный метод. Исходное изображение загружено с опцией CV_LOAD_IMAGE_GRAYSCALE. На нём рассматривается увеличенная на 30% область, найденная по прошлому методу. Суммы интенсивностей каждого столбца и каждой строки поделил на соответственно число элементов в каждом столбце (каждой строке). Получил два массива значений: XArr для столбцов и YArr для строк (все значения от 0 до 255).

    Описываю, как находил новые границы изображения. Ввёл два пороговых значения: цветовое и процентное.

    Прохожу по XArr, считаю число элементов XArr меньше цветового порога. Если их процент от общего числа меньше процентного порога, то увеличиваю на 1 минимальный X, уменьшаю на 1 максимальный X, осуществляю повторный проход в новых границах. Если их больше процентного порога, то минимальный и максимальный X - новые границы изображения. Аналогичную процедуру выполняю для Y.

    Данный метод сильно зависит от выбранных порогов и не позволяет улучшить выделение иллюстраций (по крайней мере в моей реализации).


  4. Как минимум, озадачивает уже этот код:

    Maximum := GetMaximum([abs(Row^[x].rgbtRed - Row^[x].rgbtGreen),

    abs(Row^[x].rgbtGreen - Row^[x].rgbtBlue),

    abs(Row^[x].rgbtRed - Row^[x].rgbtGreen)]);

    В третьей строчке явно нужно отнимать от синего красный (или наоборот).

    Спасибо, исправил.

    В смысле обрезаны? По краю идеально обрезаны? Т.е. у них по краям что-то типа заливки, близкой к оттенкам серого? И Вы хотите ее сохранить?

    Да, на многих иллюстрациях есть "что-то типа заливки". Я хочу сохранить эту заливку.

    На самом деле, можно попробовать обработать сразу п.4 все исходное изображение, я как-то сразу не подумал об этом, но алгоритм существенно усложнится, если на одной странице несколько иллюстраций и они расположены на ней произвольным образом. А так сначала определяем позицию каждой иллюстрации, а потом уточняем ее границы.

    На одной странице может быть и несколько иллюстраций.

    В таком случае можно сделать, например, следующее.

    1. Пропускаем изображение через данный алгоритм.

    2. Определяем зоны иллюстраций.

    3. Увеличиваем их на определенную величину (трудно сказать, какую, нужно оценить, думаю, процентов 30 будет достаточно).

    4. Строим горизонтальную и вертикальную проекцию каждого куска на исходном изображении (суммируем интенсивность каждого столбца и строки), белый фон будет давать всплески, иллюстрация - провалы.

    Попробую реализовать.


  5. А можно код увидеть?

    Я так понимаю, проблемы должны быть с самой иллюстрацией, ибо все остальное достаточно черно-белое и должно хорошо отсекаться. При увеличении порога на иллюстрации должны все более проявляться белые пятна (пиксели, достаточно близкие к оттенкам серого). Именно с ними возникают проблемы?

    ImageWidth, ImageHeight - размеры изображения.

    Data - ImageData pIplImage

    WidthStep - widthStep pIplImage

    GetMaximum - нахождение максимума в массиве.

      for y := 0 to ImageHeight - 1 do

    begin

    Row := pRGBArray(Data);

    for x := 0 to ImageWidth - 1 do

    begin

    Maximum := GetMaximum([abs(Row^[x].rgbtRed - Row^[x].rgbtGreen),

    abs(Row^[x].rgbtGreen - Row^[x].rgbtBlue),

    abs(Row^[x].rgbtRed - Row^[x].rgbtGreen)]);

    if (Maximum > Threshold) then

    begin

    Row^[x].rgbtRed := 0;

    Row^[x].rgbtGreen := 0;

    Row^[x].rgbtBlue := 0;

    end

    else

    begin

    Row^[x].rgbtRed := 255;

    Row^[x].rgbtGreen := 255;

    Row^[x].rgbtBlue := 255;

    end;

    end;

    Data := pointer(integer(Data) + WidthStep);

    end;

    Слишком большой порог - области вне иллюстраций идеально белые, но и сами иллюстрации обрезаны. По краям многих иллюстраций идёт что-то вроде фона иллюстрации - он в основном и страдает. В результате, выделяется центральный фрагмент иллюстрации вместо полной иллюстрации.

    Слишком малый порог - области вне иллюстраций очищены крайне плохо, cvFindContours считает иллюстрациями области, которые таковыми не являются. Применение дополнительной очистки шума (например, cvDilate) приводит к тем же проблемам, что и при применении большого порога - иллюстрация обрезается.

    Проблема в том, что для каждой страницы с иллюстрациями нужен свой порог, при котором изображение выделится идеально. То есть никакой константный порог не подходит для решения задачи. Нужен адаптивный порог, но непонятно, по какому алгоритму его вычислять.


  6. Точно не скажу, какие конкретно функции могут помочь, но по Вашему описанию логика решения достаточно проста.

    В ч/б изображении значения RGB компонент равны, в отличие от цветного. Почему бы не использовать этот признак? Например, обходите изображение и помечаете все пиксели с равными (ну или приблизительно равными) RGB компонентами нолями, а прочие единицами. В результате получите маску цветных иллюстраций (вероятно, с некоторым шумом).

    P.S. В принципе, можно теперь открыть документацию OpenCV и поискать функцию, которая поможет нам провести подобную обработку, и избавиться при необходимости от возможного шума.

    Реализовал пробный вариант. Приблизительное равенство определяется некоторым порогом. Для каждой отдельной иллюстрации можно подобрать порог, чтобы она определялась безошибочно. При уменьшении порога нарастает шум и сбивается работа cvFindContours. При увеличении порога возникают погрешности в определении границ. В среднем в первой реализации Ваш метод обеспечивает примерно такую же точность, как и cvMorphologyEx с CV_MOP_CLOSE.


  7. Есть отсканированная книга с набором иллюстраций. Стоит задача - отделить иллюстрации от текстовых данных. Иллюстрации - цветные, текст - визуально чёрный, фон - визуально серый. Пробовал рассматривать текст в качестве шума и использовал cvMorphologyEx с CV_MOP_CLOSE для его устранения. В результате изображения извлекаются с большой погрешностью. Какие функции в составе OpenCV могут помочь решить поставленную задачу?


  8. Пришёл к выводу, что надо создать дополнительные типы записей и указатели на них для каждого конкретного вида возвращаемых функциями cvHoughCircles и cvHoughLines данных. Например, для cvHoughLines2 и CV_HOUGH_STANDARD запись будет содержать два поля типа single. Затем получить запись через PRecord(cvGetSeqElem(Results, i)) и использовать как стандартную запись.


  9. Как видите, я вместо cvCircle писал CvRect. Оно то что-то считает, но как Вы понимаете не то, есть ли какая-то алтернатива вот этому кусочку кода на Делфи:

    float* p = (float*)cvGetSeqElem( circles, i );

    cvCircle( img, cvPoint(cvRound(p[0]),cvRound(p[1])), 3, CV_RGB(0,255,0), -1, 8, 0 );

    cvCircle( img, cvPoint(cvRound(p[0]),cvRound(p[1])), cvRound(p[2]), CV_RGB(255,0,0), 3, 8, 0 );

    Мне нужно просто вытянуть координаты кругов:

    Мне тоже интересен этот вопрос. Если интерпретировать p как указатель на вещественное число (PFloat = ^real;), то возникает естественная ошибка "E2016 Array Type Required" при обращении к p[0] и к p[1].

    Если использовать "pt: pCvPoint;" и "pt := PCvPoint(cvGetSeqElem(circles, i));", то в координатах pt x и y оказывается мусор. Каким образом в Delphi можно правильно извлечь "pCvPoint" из "pCvSeq", возвращаемого cvHoughCircles и cvHoughLines.

    Заранее спасибо за ответ.

×