Самое быстрое определение цвета RGB C++

Привет, я использовал метод getpixel, bitblt или его название (создание заголовка растрового изображения), а затем просматривал все значения. Это ОЧЕНЬ медленно. Например, если бы мне нужно было обнаружить что-то красное или определенный цвет, это заняло бы очень много времени. Должен быть более быстрый способ, верно? Я пытался использовать рабочий стол как HWND, а затем окно, которое мне нужно, чтобы найти цвета, но рабочий стол был как-то быстрее ... предположил, потому что ему нужно было искать окно, я думаю. Я получаю ВЫСОКОЕ использование процессора, используя оба метода.

void Get_Color(int x,int y,int w,int h,int &red,int &green,int &blue,int action)
{
        HDC hdc, hdcTemp;
        RECT rect;
        BYTE*bitPointer;
        HWND Desktop = GetDesktopWindow();
        hdc = GetDC(Desktop);
        GetWindowRect(Desktop, &rect);
        hdcTemp = CreateCompatibleDC(hdc);
        BITMAPINFO bitmap;
        bitmap.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        bitmap.bmiHeader.biWidth = w;
        bitmap.bmiHeader.biHeight = h;
        bitmap.bmiHeader.biPlanes = 1;
        bitmap.bmiHeader.biBitCount = 32;
        bitmap.bmiHeader.biCompression = BI_RGB;
        bitmap.bmiHeader.biSizeImage = 0;
        bitmap.bmiHeader.biClrUsed = 0;
        bitmap.bmiHeader.biClrImportant = 0;
        HBITMAP hBitmap2 = CreateDIBSection(hdcTemp, &bitmap, DIB_RGB_COLORS, (void**)(&bitPointer), NULL, NULL);
        HGDIOBJ save = SelectObject(hdcTemp, hBitmap2);
        BitBlt(hdcTemp, 0, 0, w, h, hdc, x, y, SRCCOPY);
        if(action==1)
        {
            for(int j=0;j<=w*h*4;j+=4)
            {
                red = bitPointer[j+2];
                green = bitPointer[j+1];
                blue = bitPointer[j];
                if(red<30 && green>190 && blue>190)
                {
                    break;
                }
            }   
        }
        else
        {
            for(int j=0;j<=w*h*4;j+=4)
            {
                red = bitPointer[j+2];
                green = bitPointer[j+1];
                blue = bitPointer[j];
                break;

            }   
        }
        ///RELEASE
        DeleteObject( SelectObject(hdcTemp, save) );
        DeleteDC(hdcTemp);
        DeleteDC(hdc);
        ReleaseDC(NULL,hdc);
        ReleaseDC(NULL,hdcTemp);

    }

person Hārdža    schedule 03.01.2015    source источник
comment
Вы должны определить RGB один раз, сохранить статус/значение и передать его в качестве параметра. Нет необходимости проверять наличие RGB при доступе к каждому пикселю.   -  person Thomas Matthews    schedule 03.01.2015
comment
Вы можете объяснить больше? Я не совсем понял тебя.. :D   -  person Hārdža    schedule 03.01.2015
comment
Вы имеете в виду, что я не должен использовать цикл for для циклического прохождения значений? Тогда как я могу получить цвета?   -  person Hārdža    schedule 03.01.2015
comment
Я предлагаю один раз преобразовать растровое изображение в значения RGB, а затем вы сможете обратиться к своей структуре RGB. Я предлагаю матрицу значений ‹RGB›. Ваш код каждый раз будет начинать поиск сначала.   -  person Thomas Matthews    schedule 03.01.2015
comment
Как вы думаете, какая операция больше всего загружает процессор? Потому что это очень интенсивно.   -  person Hārdža    schedule 04.01.2015
comment
Как вы думаете, может быть, это слишком много для одной темы?   -  person Hārdža    schedule 04.01.2015


Ответы (3)


Вы можете попытаться прервать поиск. Сначала ищите в красном канале и, когда это удастся, ищите значения синего и зеленого:

for (int j=0; j<=w*h*4; j+=4){
    red = bitPointer[j+2];
    if (red<30) {
        green = bitPointer[j+1];
        blue = bitPointer[j];
        if (green>190 && blue>190) {
            do_something;
        }
    } 
} 

Вы также можете попробовать ускориться с помощью арифметики указателей (но хороший компилятор легко оптимизирует первое):

for (BYTE *pRed=bitPointer+2; pRed<=bitPointer+w*h*4; pRed+=4){
    if (pRed<30) {
        green = pRed[-1];
        blue = pRed[-2];
        if (green>190 && blue>190) {
            do_something;
        }
    } 
}

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

person Jean-Baptiste Yunès    schedule 03.01.2015

Я предлагаю вам создать таблицу значений RGB из растрового изображения. Это нужно будет выполнить только один раз.

struct RGB
{
  unsigned int red;
  unsigned int green;
  unsigned int blue;
};

RGB rgb_pixels[MAX_ROWS][MAX_COLUMNS];

// ...
for (unsigned int row = 0; row < MAX_ROWS; ++row)
{
  for (unsigned int column = 0; column < MAX_COLUMNS; ++column)
  {
     unsigned red = get_red_value(row, column);
     unsigned green = get_green_value(row, column);
     unsigned blue  = get_blue_value(row, column);
     RGB pixel;
     pixel.red = red;
     pixel.green = green;
     pixel.blue  = blue;
     rgb_pixels[row][column] = pixel;
  }
}

Всякий раз, когда вашей программе требуется информация RGB из растрового изображения, индексируйте массив (rgb_pixels).
Доступ к массиву пикселей RGB будет намного быстрее, чем поиск и преобразование растрового изображения для каждого интересующего вас пикселя.

person Thomas Matthews    schedule 03.01.2015

По сути, каждый раз, когда вы вызываете свой метод, он создает совершенно новое растровое изображение и копирует его снова. Вы можете максимально ускорить свою программу, сохраняя массив цветов между вызовами Get_Color(). Вы можете поместить его в класс или глобальную переменную. У Томаса Мэтьюза есть хорошая идея для этого. Как только это будет исправлено, у Жана-Батиста Юнеса есть несколько хороших советов.

person Kyle Bowles    schedule 13.05.2015