Доступ к нескольким пикселям на чтение / запись в openCV с использованием 64-битных операций - PullRequest
0 голосов
/ 07 ноября 2019

Я новичок в openCV. Я редактирую изображение, и мне нужно читать и писать непрерывные пиксели на больших прямоугольных участках изображения, но не на всем изображении. Мои входные изображения имеют одноканальную серую шкалу, с CV_16UC1 в качестве входа и CV_8UC1 в качестве вывода. В настоящее время я обращаюсь к пикселям с помощью MatConstIterator _.

Mat image, image_read = imread(infilename, 0);
image_read.convertTo(image, CV_16UC1);
//...define img_dim_y, img_dim_x
Mat imout(img_dim_y, img_dim_x, CV_8UC1);

MatConstIterator_<uint16_t> pin = imageIn.begin<uint16_t>(), pixel_in_end = imageIn.end<uint16_t>();
MatIterator_<uint8_t> pixel_out = imageOut.begin<uint8_t>();
for(; /*selected pixel in a patch*/; ++pixel_out , ++pixel_out)
        *pixel_out = My_transform(*pixel_in);

Это ограниченная пропускная способность памяти, и она тратит все свое время на чтение и запись пикселей со скоростью 10 микросекунд на пиксель. Моя машина довольно современная, поэтому она намного медленнее, чем тактовые частоты ~ МГц. Для 64-битной машины должна быть возможность считывать сразу 4 16-битных пикселя и записывать 8 8-битных пикселов одновременно, используя несколько операций сдвига. Это ускорит конвейер как минимум в 4-5 раз. Как я могу получить эти данные от OpenCV Mat?

1 Ответ

0 голосов
/ 07 ноября 2019

Я нашел способ сделать что-то подобное. Следующее будет считывать в пикселях 4 за раз, но оно будет ошибочно в случайных местах после считывания части изображения.

//For a Mat img formatted as a CV_16UC1
uint8_t* alignas(64) Data = (uint8_t*)img.data;
for(int i = 0; /*selected pixel in a patch*/; i += 8){
    uint16_t p0, p1, p2, p3; //pixels
    uint64_t word = reinterpret_cast<uint64_t*>(Data)[i];
    p0 =  (word & 0x00000000000000FF)        + ((word & 0x000000000000FF00) >> 8);
    p1 = ((word & 0x0000000000FF0000) >> 16) + ((word & 0x00000000FF000000) >> 24);
    p2 = ((word & 0x000000FF00000000) >> 32) + ((word & 0x0000FF0000000000) >> 40);
    p3 = ((word & 0x00FF000000000000) >> 48) + ((word & 0xFF00000000000000) >> 56);
    //do things with pixels
}
...