2015-12-15 4 views
1

В соответствии с этим сообщением OCR: Difference between two frames, теперь я знаю, как найти различия в пикселях между двумя изображениями с помощью OpenCV.OCR & OpenCV: разница между двумя кадрами на изображениях с высоким разрешением

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

Мое приложение использует декодер RLE для декодирования сжатых кадров видео. Как только кадр декодируется, я хотел бы сравнить текущий кадр с предыдущим, чтобы сохранить различия между двумя кадрами на вкладке «Мат», например.

Целью всего этого является возможность проведения анализа на разных пикселях и проверки наличия латинского символа. Это позволяет мне уменьшить количество пикселей для анализа и сэкономить драгоценное время.

Если у кого-то есть другие идеи вместо этого, чтобы выполнять такие операции, не стесняйтесь предлагать его, пожалуйста.

Благодарим за помощь.

РЕДАКТИРОВАТЬ 1: Пример двух изображений с высоким разрешением экрана компьютера. На данный момент это прекрасный пример того, что я пытаюсь проанализировать. Как мы видим, есть просто окно как разница между двумя большими изображениями, и я бы хотел проанализировать только новое окно «Challenge» для любого персонажа.

First image

Second image

EDIT 2: Я пытаюсь настроить алгоритм в зависимости от анализируемых данных. Обычно на двух следующих рисунках я получаю только зеленые линии в виде различий и никакого текста вообще (что является самым интересным). Я пытаюсь лучше понять, как все это работает.

первое изображение:

TestImg1

второе изображение:

TestImg2

третье изображение: ResultImg

Как вы можете видеть, у меня есть только те зеленые линии и никогда текст (в лучшем случае я могу иметь лишь одну букву при уменьшении countours [я] .size())

+0

Я не уверен, если это поможет вам решить вашу проблему, от моего опыта OpenCV не может справиться видео в полном разрешении (по крайней мере, в окнах http://stackoverflow.com/questions/17993677/opencv-capture-image-from-webcam-without-post-processing/17995736#17995736) – Engine

+0

Можете ли вы разместить два изображения? Или публичные ссылки на изображения с высоким разрешением? – Miki

+0

@ Miki Я только что отредактировал мой пост –

ответ

1

В дополнение к сообщению вы упомянули , вам необходимо:

  • При бинаризации маски используйте пороговое значение выше 0, чтобы удалить небольшие различия.
  • Снимите шум.Вы можете найти все подключенные компоненты и удалить меньшие.
  • Найдите область более крупных подключенных компонентов. Вы можете использовать convexHull и fillConvexPoly, чтобы получить маску разных объектов на экране.
  • Скопируйте второе изображение на новое изображение с заданной маской.

Результат будет выглядеть так:

enter image description here

Код:

#include <opencv2/opencv.hpp> 
#include <vector> 
using namespace std; 
using namespace cv; 

int main() 
{ 
    Mat3b img1 = imread("path_to_image_1"); 
    Mat3b img2 = imread("path_to_image_2"); 

    Mat3b diff; 
    absdiff(img1, img2, diff); 

    // Split each channel 
    vector<Mat1b> masks; 
    split(diff, masks); 

    // Create a black mask 
    Mat1b mask(diff.rows, diff.cols, uchar(0)); 

    // OR with each channel of the N channels mask 
    for (int i = 0; i < masks.size(); ++i) 
    { 
     mask |= masks[i]; 
    } 

    // Binarize mask 
    mask = mask > 100; 

    // Results images 
    vector<Mat3b> difference_images; 

    // Remove small blobs 
    //Mat kernel = getStructuringElement(MORPH_RECT, Size(5,5)); 
    //morphologyEx(mask, mask, MORPH_OPEN, kernel); 

    // Find connected components 
    vector<vector<Point>> contours; 
    findContours(mask.clone(), contours, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE); 

    for (int i = 0; i < contours.size(); ++i) 
    { 
     if (contours[i].size() > 1000) 
     { 
      Mat1b mm(mask.rows, mask.cols, uchar(0)); 

      vector<Point> hull; 
      convexHull(contours[i], hull); 


      fillConvexPoly(mm, hull, Scalar(255)); 

      Mat3b difference_img(img2.rows, img2.cols, Vec3b(0,0,0)); 
      img2.copyTo(difference_img, mm); 

      difference_images.push_back(difference_img.clone()); 
     } 
    } 

    return 0; 
} 
+0

Это работает очень хорошо, это довольно быстро и делает именно то, что я искал. Спасибо вам за помощь Мики! –

+0

У меня все еще есть один вопрос. Wy вы отфильтровали контур [i] .size(), чтобы сохранить только тех, у кого есть 1000 или более элементов? Это способ устранить каждую «маленькую» разницу между кадрами и сохранить только большие матчи? Является ли 1000 средним числом? –

+0

@ DylanAlvaro предназначен для удаления небольших капель, то есть блоков, которые имеют (вид) периметра меньше 1000. Вы можете использовать любое другое значение достаточно большое или вычислить его из некоторых статистических данных на вашем изображении. Эта 'mask = mask> 100;' будет устранять небольшие различия (<100) между двумя изображениями. – Miki