Jump to content
Compvision.ru

All Activity

This stream auto-updates     

  1. Yesterday
  2. Last week
  3. Earlier
  4. Можно тогда еще посмотреть Aruco, она встроена в OpenCV.
  5. Доска отслеживается с целью получить метку, которая будет всегда находиться в кадре, для того чтобы по ней, в дальнейшем, считать координаты движущегося объекта, к которому она привязан. Я сделал фейковое усреднение по нескольким кадрам. теперь метка не скачет. Попробую либу, которую вы посоветовали, чтобы повысить точность определения, если это конечно имеет смысл, и точность действительно повысится.
  6. Я не в курсе цели трекания шахматки в вашем случае, но если это не для калибровки, то попробуйте эту либу: http://nghiaho.com/?page_id=576 Или фильтруйте уже 6D положение доски. Там все равно решается переопределенная СЛАУ и выдается решение по методу наименьших квадратов. Если делаете сглаживание для каждой точки, выглядеть будет конечно лучше, но точности вряд ли добавит. Как компромисс, используйте сглаженное 6D положение и проецируйте обратно на экран измеренные по доске точки модели.
  7. Благодарю, попробую.
  8. Точки могут дрожать, например, из-за того, что маленькое разрешение, а угол попадает между пикселями. Можно попробовать вызывать cv::findCornersSubpix. Я когда-то для лицевых точек прмкручивал оптический поток и Калмана.
  9. Добрый день. В программе осуществляется поиск углов шахматной доски на фотографии. Для этого используется FindChessboardCorners в C#. По найденным углам строятся линии. Дело в том, что точки (когда вывожу их все на изображение, и когда только 4 угла), при определении "дрожат". Не знаю, с чем это связано. Пробовал разные флаги для этой функции, пробовал ставить на жесткую подставку - все равно. Есть ли какие-нибудь способы более точного определения с помощью готовых методов в OpenCV? Я пытался сделать следующим образом: Подсчитать медиану всех расстояний между точками вдоль каждой стороны, и применить ее для всех, но это работает только если камера не под наклоном. Файл с коротким видео, как это выглядит (я понимаю, что почти все тут это наблюдали при калибровке, но всё же). for compvision.mp4
  10. Ну, я ж специально на атомных функциях делал. Вообще, производительность получилась очень хорошая, как ни странно. Надо придумать, почему так получилось.. Как вариант, такое обоснование: 1. Отфильтрованных точек существенно меньше, чем число точек в исходном массиве (примерно 50к против 900к), поэтому атомная функция вызывалась не очень часто. 2. Компоновка выходного массива выполняется параллельно и с хорошей слитностью адресов памяти. Возможно, как раз второй пункт имеет решающее значение для производительности. Потому что в непосредственно фильтрации ничего ресурсоемкого нет.
  11. Корень можно не извлекать, лучше в квадрат возвести радиус. Ну и, как мне видится, атомный доступ весь эффект сводит на нет. Может в параллель только флаги расставить, а скомпоновать массив на CPU ?
  12. __global__ void TubeFilter(float *in, float *out, float *limits, uint *out_size, uint in_size) { __shared__ uint save_count; // count of successfully filtered items in current block if (threadIdx.x == 0) { save_count = 0; // initialize by some one thread } __syncthreads(); uint read_idx = blockIdx.y * blockDim.x * blockDim.y * gridDim.x + blockIdx.x * blockDim.x * blockDim.y + threadIdx.x; if (read_idx >= in_size) { return; } uint r3 = read_idx * 3; // each thread works with all 3 dimensions of a point float x = in[r3]; float y = in[r3 + 1]; float z = in[r3 + 2]; bool save_flag = false; // true if the filter conditions are complied uint save_idx = 0; // the thread will write to this index of out array if (sqrt(x*x + y*y) <= limits[0] && z >= limits[1] && z <= limits[2]) { save_flag = true; save_idx = atomicAdd(&save_count, 1); } __syncthreads(); __shared__ uint first; // first write position of current block if (threadIdx.x == 0) { // increase the common size of out array in global memory first = atomicAdd(out_size, save_count); } if (save_flag) { uint w3 = (first + save_idx) * 3; out[w3] = x; out[w3 + 1] = y; out[w3 + 2] = z; } } Вроде получилось ядро фильтрации. На двух atomicAdd, один из них для значения в shared памяти, второй - для global памяти. Проревьюйте, пожалуйста, кому интересно. Здесь реализован фильтр координат, попадающих в цилиндрическую область заданного радиуса и высоты. in - входной массив 3D координат - float x, y, z координаты. out - выходной массив 3D координат. В него пишутся только точки, удовлетворяющие фильтру. limits - параметры фильтрации: [0] - радиус, [1] - минимальное значение по оси Z, [2] - максимальное значение по Z. out_size - текущий размер выходного массива. Аллоцирован в global памяти. Изначально установлен в host-функции в 0, затем увеличивается в каждом блоке на количество отфильтрованных точек. in_size - размер входного массива. Не меняется.
  13. Спасибо, на него тоже посмотрю. Thrust по любому на базовых CUDA примитивах построен, чудес наверное не стоит от него ждать.
  14. Может Trust заюзать ? Помножить на 0 все что отбрасываем, отсортировать и обрезать вектор по первому нулю.
  15. Ну да, свертка.. редукция - это ж одно и то же. Я про них и говорю. Для суммирования они подходят - итеративно общий результат так получать удобно. А в моей фильтрации по идее итерировать не надо: можно за один проход все вычислить, результат зависит только от одного элемента. Зависимости между тредами возникают только из-за адреса, в который результат надо записать. Например: задача отфильтровать значения по порогу 100. Для входного массива [15, 131, 618] результат будет [131, 618]. То есть вторая нить (которой досталось отфильтровать значение 131) должна как-то понять, что писать в выходной массив надо по индексу 0, т.к. первая нить (фильтрующая 15) в выходной массив свое значение не пропускает. Смотрю сейчас на atomic functions. Думаю, что на них надо делать, но не понимаю, как они с абсолютным проседанием производительности борятся. Ну либо все еще не улавливаю всех возможностей редукции..
  16. Я про свертку не писал - редукция же. Каждый второй поток складывает полезные результаты в свой кусочек памяти и запоминает сколько и где, потом каждый четвёртый за двумя предыдущими и т.д. Теоретически, это должно сработать быстро.
  17. Почитал про свертку еще. Так и не понял, как ее использовать в описанной выше задаче. Свертка во всех примерах используется для операций типа подсчета суммы всех элементов массива, т.е. когда размер выходного массива заранее известен - фиксированный, или кратен размеру входного массива, или строго зависит от него. Если не сложно, опиши немного подробнее как применить свертку для фильтрации данных.
  18. Такая презентация на эту тему встречалась? http://developer.download.nvidia.com/compute/cuda/1.1-Beta/x86_website/projects/reduction/doc/reduction.pdf
  19. Добрый день, Хочу на простом примере распараллеливания операции свёртки понять как выбирать оптимальные значения для числа блоков, числа нитей и кошерно ли делать цикл внутри нити или надо максимально увеличить число блоков и нитей ? Допустим матрица размером M*N Допустим число ядер cuda, известное из документации. Пока понял что для случая большой матрицы(изображения) лучше топить на число нитей в блоке так как всю её за раз не посчитаешь и планировщик нитей в варпе должен работать по идеи быстрей планировщика блоков, но кто быстрей внутренний цикл в ните или планировщик блоков ? Когда матрица маленькая и может посчитаться за один цикл(распараллевание не больше чем число ядер), то я так понимаю надо наоборот число нитей надо брать в 1 варп(32), а число блоков надо брать число ядер/32.
  20. В составе PCL есть модуль компрессии. http://pointclouds.org/documentation/tutorials/compression.php Попробую его. Но с форматом видео контейнера вопрос все еще полностью открыт. Насколько я понимаю, тут тоже сжатие с потерями реализовано - теряется точность координат и количество сохраненных точек. В параметрах указывается сколько точек сохранять на единицу объема (на кубический сантиметр или миллиметр).
  21. Операция называется свертка. Информации много, например: https://habr.com/ru/post/114489/ https://ru.wikipedia.org/wiki/Оператор_Собеля Для 60 градусов ядра 3х3 маловато.
  22. Про специальные форматы не слышал, хотя может и есть. Для сжатия можно попробовать snappy 250 Mб/сек скорость сжатия. Как экзотический вариант, выделить обычные кадры подходящего размера, и сохранять в них как в буферах данные о точках. Только сжатие с потерями тут не прокатит Можно попробовать применить какую нибудь из баз данных, типа HDF5 или LMDB, тем более есть поддержка в OpenCV.
  23. С помощью функции cv::filter2D() нужно создать фильтр, который находит в изображении только прямые, наклоненные под углом 60 градусов. Примените его к достаточно интересной сцене и выведите результат car = cv2.imread("car.jpg") kernel = np.ones((3,3)) #cv2.filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]]) DST=cv2.filter2D(car, 14, kernel) cv2.imshow("DST",DST) cv2.waitKey(0) cv2.destroyAllWindows() Я немного не осилил documentation и до меня не дошло, как задать именно 60 градусов в данной функции. Буду рад, если кто-нибудь поможет с реализацией и объяснит,как работает якорь в данной функции.
  24. Спасибо, большое. Видел такое раньше, но не понял до конца значит. Пошел изучать..
  25. Техника называется reduction, когда сначала все потоки пишут свои значения в результат, потом половина из них пишет валидные значения, затем ещё половина и т.д. Пока не останется один поток, определяющий финальный размер результата.
  26. Коллеги, кто имеет опыт в CUDA, подскажите, пожалуйста. Возможно ли в принципе в кернел-фукнции выполнить фильтрацию данных? Так, чтобы размер данных на выходе функции был переменным. Пример задачи: На входе массив значений float, в результирующий массив надо записать только те значения, которые превышают заданный порог. Как такая задача решается? Не могу сообразить, как заставить треды выполнить такую синхронизированную запись в выходной массив. Тут получается, что индекс в выходном массиве априорно не известен, зависит от реультатов работы остальных нитей.
  27. Друзья, как сейчас обстоит дело с форматами записи/стриминга Point Cloud video? Попробовал сделать сохранение потока напрямую как есть, в тривиальном бинарном формате: количество точек в облаке (фиксированная длина), массив данных для каждого кадра (переменная длина, зависимая от первого поля). Оно конечно работает в каком-то смыле - записать и воспроизвести последовательность облаков можно. Но размер файлов получается огромный, т.к. запись идет без сжатия. И естественно, с позиционированием в файле проблема. Может есть какие-то стандарты или даже готовые библиотеки для этого?
  28. Сделал обе эти функции на CUDA, отлично работают. Готовых в librealsense и pcl не нашел.
  1. Load more activity
×