Сундучок на базе Raspberry Pi, который распознает ваше лицо. Установка Open CV (Linux) Шаг #1: Подготовка сундучка

To install OpenCV on Raspberry Pi, you need Raspberry Pi (Pi2 preferably) , Pi camera, and internet connection to Raspberry Pi.

Copy this image to correct size SD Card. To do this correctly please refers the detailed instructions at https://www.raspberrypi.org/documentation/installation/installing-images/

Now since your SD card is ready, Boot your Pi. First thing you want to do is Enable Camera.
To do this run

Sudo raspi-config

and chose Enable Camera (menu 6) also chose the correct speed for your Raspberry Pi from Overclock option (menu 8).

Reboot your Raspberry Pi. Now its is time to Install python wrapper for OpenCV, to do this run

Sudo apt-get install python-opencv
sudo pip install imutils

Now we are almost done. Let"s test the Pi camera connected to Raspberry Pi for proper operation. For this on command prompt run,

Raspistill -o cam.jpg

The red light on the Pi camera will come on and a picture will be stored in cam.jpg file. Now we are all set to do some serious face tracking using Raspberry Pi. You can download the face tracking sample code using haar cascade from .
You can run this code from Raspberry Pi command line.

Python face_detect.py haarcascade_frontalface_default.xml

If the face is found in an image captured by camera, python program will print "Found 1 faces!. " Below is brief description of how the code work.

From picamera.array import PiRGBArray from picamera import PiCamera import time import cv2 import sys import imutils # Get user supplied values cascPath = sys.argv # Create the haar cascade faceCascade = cv2.CascadeClassifier(cascPath) # initialize the camera and grab a reference to the raw camera capture camera = PiCamera() camera.resolution = (160, 120) camera.framerate = 32 rawCapture = PiRGBArray(camera, size=(160, 120))

This imports the required libraries and open the haar cascade file
Raspberry pi camera is intialized and the streme of images is collectd from camera one by one. Resolution is selected to be 162X120 for fast detection of faces.

Image = frame.array gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

each image is picked from the camera and is loaded in nmupy array. Image is then converted to a grayscale image. This gray scale image is fed to facedetection alogorithm, with some minimum size setting

Faces = faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30), flags = cv2.cv.CV_HAAR_SCALE_IMAGE) for (x, y, w, h) in faces: cv2.circle(image, (x+w/2, y+h/2), int((w+h)/3), (255, 255, 255), 1)

if any valid faces are found in image, function will return the list of faces with positions. We draw a white circle around each face and display results.

Одно время я увлекался сборкой роботов-машинок на Ардуино и Raspberry Pi. Играть в конструктор мне нравилось, но хотелось чего-то большего.

И как-то раз, блуждая по Алиэкспрессу, я набрел на алюминиевое шасси для танка. Выглядело это творение в сравнении с машинками из пластика как Феррари в сравнении с телегой.

Я сделал себе подарок на Новый год, танк приехал, был собран и дальше надо было его оживлять. Я снял с машинки собствено Raspberry, конвертер питания, контроллер мотора и батарею. Все это было поставлено на танк и радостно заработало.

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

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

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

Идея была в том, чтобы замаркировать заметные объекты в комнате (диван, телевизор, стол) разноцветными кружками и научить робота ориентироваться по цвету.

Средствами OpenCV искались контуры нужного цвета (с допустимой толерантностью), потом среди контуров искалась окружность.

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

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

Поиск кружка красного цвета:

Import cv2 import numpy as np import sys def mask_color(img, c1, c2): img = cv2.medianBlur(img, 5) hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) mask = cv2.inRange(hsv, c1, c2) mask = cv2.erode(mask, None, iterations=2) mask = cv2.dilate(mask, None, iterations=2) return mask def find_contours(img): gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (5, 5), 0) thresh = cv2.threshold(blurred, 30, 255, cv2.THRESH_BINARY) thresh = cv2.bitwise_not(thresh) im2, cnts, hierarchy = cv2.findContours(thresh, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE) cp_img = img.copy() cv2.drawContours(cp_img, cnts, -1, (0,255,0), 3) return cp_img def find_circles(img): gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) blurred = cv2.medianBlur(gray,5) circles = cv2.HoughCircles(blurred,cv2.HOUGH_GRADIENT,1,20,param1=50,param2=30,minRadius=0,maxRadius=0) cimg = img if circles is not None: circles = np.uint16(np.around(circles)) for i in circles: cv2.circle(img,(i,i),i,(255,0,0),2) cv2.circle(img,(i,i),2,(0,0,255),3) print "C", i,i,i return cimg def find_circle(img, rgb): tolerance = 4 hsv = cv2.cvtColor(rgb, cv2.COLOR_BGR2HSV) H = hsv c1 = (H - tolerance, 100, 100) c2 = (H + tolerance, 255, 255) c_mask = mask_color(img, c1, c2) rgb = cv2.cvtColor(c_mask,cv2.COLOR_GRAY2RGB) cont_img = find_contours(rgb) circ_img = find_circles(cont_img) cv2.imshow("Image", circ_img) cv2.waitKey(0) if __name__ == "__main__": img_name = sys.argv img = cv2.imread(img_name) rgb = np.uint8([[]]) find_circle(img, rgb)
Цветовое распознавание стало заходить в тупик, я отвлекся на каскады Хаара, используя танк для фотоохоты на кота. Кот неплохо маскировался, заставляя каскад ошибаться в половине случаев (если кто не знает, OpenCV идет со специально обученным на котиках каскадом Хаара - бери и пользуйся).

Охота на кота имела полезные последствия для робота - поскольку в статичную камеру не всегда можно было поймать объект охоты, я поставил штатив с двумя сервомоторами (и PWM-модуль для управления ими через Raspberry).

Продолжая изыскания на тему, что можно выжать из фоток комнаты, я закономерно пришел к нейросетям. Заглотив туториал по Tensorflow, я обработал его детектором фотки с танка и результаты были многообещающими - телевизор, стол, диван, кот, холодильник распознавались безошибочно.

Эксперименты эти проводились на компьютере, и дело осталось за малым - перенести TF на Raspberry Pi. К счастью, на гитхабе живет уникальный человек, который набрался терпения и прорвался через установку всех зависимостей и многочасовое время компиляции - и выложил в общий доступ собранный Tensorflow для Raspberry Pi.

Однако, дальнейшее изучение темы открыло, что OpenCV не стоит на месте и его контрибуторы выпустили модуль DNN (Deep Neural Networks), предлагающий интеграцию с нейросетями, обученными на TensorFlow. Это решение гораздо удобнее в разработке, плюс отпадает необходимость в самом TF. Пришлось немного поколдовать, так как свежая версия Mobile SSD нейросети для TF, уже не подхватывалась последней версией OpenCV. Надо было искать
и проверять рабочую версию Mobile SSD. Плюс к этому, DNN нормально работает только под OpenCV 3.4, а этой версии для Raspberry я не нашел. Пришлось собирать самому, благо это гораздо проще, чем возиться с TensorFlow. При этом собрать OpenCV под последнюю весию Raspbian (Stretch) не удалось, а вот на последней версии предыдущего поколения (Jessie) все взлетело как надо.

Пример кода, использующий DNN и не использующий Tensorflow.

Несколько файлов, отвечающих за имена объектов были вытянуты из TF и зависимость от самого TF убрана (там было только чтение из файла).
Исходный код на гитхабе.

Import cv2 as cv import tf_labels import sys DNN_PATH = "---path-to:ssd_mobilenet_v1_coco_11_06_2017/frozen_inference_graph.pb" DNN_TXT_PATH = "--path-to:ssd_mobilenet_v1_coco.pbtxt" LABELS_PATH = "--path-to:mscoco_label_map.pbtxt" tf_labels.initLabels(PATH_TO_LABELS) cvNet = cv.dnn.readNetFromTensorflow(pb_path, pb_txt) img = cv.imread(sys.argv) rows = img.shape cols = img.shape cvNet.setInput(cv.dnn.blobFromImage(img, 1.0/127.5, (300, 300), (127.5, 127.5, 127.5), swapRB=True, crop=False)) cvOut = cvNet.forward() for detection in cvOut: score = float(detection) if score > 0.25: left = int(detection * cols) top = int(detection * rows) right = int(detection * cols) bottom = int(detection * rows) label = tf_labels.getLabel(int(detection)) print(label, score, left, top, right, bottom) text_color = (23, 230, 210) cv.rectangle(img, (left, top), (right, bottom), text_color, thickness=2) cv.putText(img, label, (left, top), cv.FONT_HERSHEY_SIMPLEX, 1, text_color, 2) cv.imshow("img", img) cv.waitKey()
В общем, теперь фотки танка можно распознавать нейросетью, и это очень важный шаг в навигации в плане узнавания ориентиров. Тем не менее, одних картинок для полноценной навигации не хватало, требовалось измерять расстояния до препятствий. Так у робота появился эхолот. Чтобы подключить эхолот к Raspberry, надо немного потрудиться - эхолот возврашает сигнал на 5V, а Raspberry принимает 3.3V. На коленке эту проблему решают в основном резисторами на бредборде, однако мне не хотелось городить такую кустарщину на роботе. В итоге была найдена микросхема Level Shifter, которая делает все, что надо, и размером она с ноготь.

Кроме того, я озаботился внешним видом робота - не очень нравилось, что микросхемы и камера с эхолотом были прилеплены к картонкам. Развитие техники в нашем мире позволяет резать пластик лазером с разумными затратами времени и денег. В общем, я нашел мастерскую с лазерным станком, потратил немного времени на изучение инструкции к этой чудо-машине и далеко не с первой попытки вырезал панели под микросхемы и камеру с эхолотом.

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

REST интерфейс, который предоставляет робот в качестве базы для дальнейшего использования:

GET /ping GET /version GET /name GET /dist POST /fwd/on POST /fwd/off POST /back/on POST /back/off POST /left/on POST /left/off POST /right/on POST /right/off POST /photo/make GET /photo/:phid GET /photo/list POST /cam/up POST /cam/down POST /cam/right POST /cam/left POST /detect/haar/:phid POST /detect/dnn/:phid

Anyone who has dealt with image processing in relation to the Raspberry Pi will sooner or later come across the OpenCV library. It provides many very useful features such as face recognition, the creation of depth maps (stereo vision, optical flow), text recognition or even for machine learning. In addition, OpenCV (Open Source Computer Vision) can be integrated into both its C ++ files and its Python scripts.
Especially in terms of feature recognition in images taken by the Raspberry Pi, OpenCV is very helpful.

This advanced tutorial shows how to install OpenCV on the Raspberry Pi and how to integrate it into Python.

For the time being, I would like to recommend everyone a Raspberry Pi Model B to use, because this is a lot more powerful than its predecessor. Even on a Raspberry Pi B + compiling takes about 6 times as long, with a Pi 2 in total “only” takes about an hour.

First of all, we update the package lists:

sudo apt - get update && sudo apt - get upgrade && sudo rpi - update

A reboot is necessary if it has been updated.

Sudo reboot

Then you can install all the important tools and libraries needed for OpenCV (installation takes a few minutes).

sudo apt - get install build - essential git cmake pkg - config libjpeg8- dev libtiff4 - dev libjasper - dev libpng12 - dev libavcodec- dev libavformat - dev libswscale - dev libv4l - dev libgtk2. 0 - dev libatlas- base - dev gfortran

If everything worked, we could clone OpenCV from git . This step also takes a few minutes.

git clone https : / / github .com / Itseez / opencv .git && cd opencv &&git checkout 3.0.0

Whether version 3.0 or 2.4 of OpenCV is taken is up to you. Depending on the application, one of the versions may be better suited.

Afterwards, OpenCV can be compiled. You can either use Python 2.7 or Python 3+. There are some differences between the versions, especially as some libraries are not (yet) executable with Python 3+. However, this mainly affects smaller libraries, as common libraries (NumPy, SciPy, etc.) usually provide the respective files for both versions.

In this tutorial, I use Python 2.7. If you already have Python installed and want to know which version is installed, you can simply enter python into the console and get the exact version at the beginning (the command for Python 3+ is python3). If you do not have a Python installed, you can install it by following the steps below:

sudo apt - get install python2 . 7 - dev

We also need the package management tool pip , which installs NumPy right away:

Cd ~ && wget https : / / bootstrap .pypa .io / get - pip .py && sudo python get - pip .py

Now we can simply install via pip NumPy. NumPy is a library that makes it very easy to perform array operations in Python.

pip install numpy

But now to compile OpenCV. For this purpose, a build folder must be created in which the compiled files land:

Cd ~ / opencv && mkdir build && cd build cmake - D CMAKE_BUILD_TYPE = RELEASE - D CMAKE_INSTALL_PREFIX = / usr / local - D INSTALL_PYTHON_EXAMPLES = ON - D INSTALL_C_EXAMPLES = ON - D OPENCV_EXTRA_MODULES_PATH = ~ / opencv_contrib / modules - D BUILD_EXAMPLES = ON . .

Now you can finally compile. This step takes (depending on Raspberry Pi model) quite a long time (on my Pi 2 about an hour). To use all four cores to compile on the Raspberry Pi 2, type in the following:

make - j4

If the compilation has worked without problems, we can install OpenCV:

Sudo make install && sudo ldconfig

Open Source Computer Vision Library

Это библиотека для языка программирования Python упрощающая работу с машинным зрением (раздел машинного обучения - Machine Learning).
Для понимания предлагаю рассмотреть процесс распознавания лица (классика), если б не существовало OpenCV:
  1. Перво-наперво необходимо иметь огромную коллекцию изображений с лицами людей и без них
  2. Структурировать этот набор - сопоставить каждому изображению пояснение: присутствует ли на нем человеческое лицо.
  3. Равномерно и правильно разделить структурированную коллекцию на обучающую и контрольную выборку.
  4. Далее путем перебора и сочетания разнообразных методов машинного обучения (“дерево”, “случайный лес”, “градиентный спуск”, “ближайшие соседи” и т.д.) составить нейросеть, дающую приемлемый результат распознавания как на обучающей, так и на контрольной выборке. На этот этап могут уйти месяцы(!) (в зависимости от доступных вычислительных ресурсов)
А разработчики OpenCV предоставляют всем бесплатный набор первоклассных алгоритмов машинного зрения для различного применения - бери, да используй!)

ПРЕДУПРЕЖДЕНИЕ:

  • Далее рассматриваются тонкости установки OpenCV на Raspbian, однако, инструкция вполне универсальна для всех дистрибутивов семейства Debian
  • установка OpenCV занимает много времени (2-3 часа), однако не обязательно проходить весь путь за один раз - можно остановиться и продолжить с того же места.
  • Потребуются .
  • Установку будем производить на Raspberry Pi 3 на чистый, только что проинсталлированный Raspbian Desktop последней версии. см.

Подготовка

Потребуется 7 Гб свободного места на флешке.
Чтобы проверить наличие свободного места на флешке откроем терминал (Ctrl + Alt + T) и введем команду
df -h
Если места недостаточно, хотя объем флешки должен позволять, то стоит проверить расширена ли файловая система на весь доступный объем (в новых версиях дистрибутива это теперь делается по умолчанию - от апреля 2018 года).
Если система не очень новая, тогда можно зайти в раздел главных настроек
sudo raspi-config
и выбрать первый пункт “1. Expand File System”, а затем перезагрузить Малину

Установка необходимых пакетов

Если обновления давно не проводились, то желательно произвести их сейчас
sudo apt-get update -y && sudo apt-get upgrade -y
Устанавливаем комплект пакетов для сборки программ из исходников
sudo apt-get install build-essential cmake pkg-config -y
Затем устанавливаем комплект библиотек для работы с графическим контентом разных форматов
sudo apt-get install libjpeg-dev libtiff5-dev libjasper-dev libpng12-dev -y
Далее тоже самое для видео контента
sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev -y sudo apt-get install libxvidcore-dev libx264-dev -y
Ставим пакет компиляции модуля highgui для вывода изображений и интерфейсов на экран
sudo apt-get install libgtk2.0-dev -y
И напоследок библиотека линейной алгебры и компилятор Фортрана:
sudo apt-get install libatlas-base-dev gfortran -y

Python

Далее устанавливаем Питон (ну или Пайтон). Базовые версии 2,7 и 3 уже вшиты в Raspbian, однако понадобятся дополнительные пакеты:
sudo apt-get install python2.7-dev python3-dev -y
Далее для Питона (ну или Пайтона) рекомендую установить утилиты virtualenv и virtualenvwrapper - это аналог ’а только для Питона, позволяют работать с Питоном в выбранном “виртуальном окружении” - наборе пакетов определенных версий (аналоги гемсетов Руби) - это удобно при работе над несколькими проектами с различными наборами библиотек (и особенно различными версиями библиотек): чтоб переключиться на, допустим Python 2.7 c OpenCV 3.1 достаточно будет ввести в терминале всего одну команду. Устанавливаем:
sudo pip install virtualenv virtualenvwrapper sudo rm -rf ~/.cache/pip echo -e "\n# virtualenv and virtualenvwrapper" >> ~/.profile echo "export WORKON_HOME=$HOME/.virtualenvs" >> ~/.profile echo "source /usr/local/bin/virtualenvwrapper.sh" >> ~/.profile source ~/.profile
На этом зависимости установлены.
Создаем виртуальное окружение с помощью virtualenv. И тут же стоит определиться с версией Питона - если цель - это создание проекта с нуля, тогда стоит выбрать python3, а иначе - python2
В процессе исторического развития языка Python во время актуальности версии 2.7 было написано очень много хороших программ. И даже сейчас во времена стабильных 3.5 версий Python 2.7 не забыт до сих пор и активно используется и поддерживается - произошло ветвление. Так же и с библиотеками Питона - не все будут работать одинаково хорошо как на 2.7 так и на 3.5
mkvirtualenv cv -p python3
Убеждаемся, что сейчас находимся в созданном виртуальном окружении cv. Это можно узнать по сочетанию “(cv)” в консоли у текущей активной строки: И наконец устанавливаем библиотеку Numpy для удобной работой с массивами и матрицами больших размерностей
pip install numpy

Скачивание Open CV из репозитория

Создадим папку для библиотеки в домашней директории и перейдем в нее
cd ~ mkdir opencv cd opencv/
Определимся с версией OpenCV.
С момента выхода версии 3.0, старые версии 2.4.х продолжают поддерживаться и выпускаться и между ними имеются серьезные отличия . К примеру пакет дополнительных модулей ‘contrib’ доступен только для новых версий 3+.
Перейдем на домашнюю страницу проекта в раздел “Releases” . Предлагаю далее устанавливать свежую версию (3+ а не 2.4.х.х) и брать не самый крайний релиз:
Таким образом выбор пал на версию 3.4.0.
Чтоб получить ссылку для скачивания перейдем в офф. репозиторий Open CV в раздел релизов: https://github.com/opencv/opencv/releases и скопируем ссылку на zip-архив выбранной версии:
Возвращаемся к Raspberry.
Находясь в папке /opencv выполним команду для скачивания исходников:
wget -O opencv.zip https://github.com/opencv/opencv/archive/3.4.0.zip
эта команда скачает архив и переименует его в opencv.zip
Распакуем скачанный архив и после удалим его:
unzip opencv.zip rm opencv.zip
Скачаем и распакуем ту же версию дополнительных модулей contrib (в данном случае - 3.4.0). Страница релизов офф. репозиотрия: https://github.com/opencv/opencv_contrib/releases
wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/3.4.0.zip unzip opencv_contrib.zip rm opencv_contrib.zip
В итоге должно получиться следующее (команда ls показывает содержимое текущей папки):

Компиляция и установка OpenCV

Еще раз убедимся, что находимся в созданном виртуальном окружении для OpenCV (глава установки Python). Если окружение уже точно было создано, то перейти в него можно командой workon cv
Переходим в папку распакованного архива OpenCV (версия, и соответственно, название папки может отличаться):
cd opencv-3.4.0/
Далее выполняем серию команд для запуска процесса сборки инсталлятора.
Это 3 команды - последняя многострочная, в ней ОСОБОЕ внимание обращаем на путь к папке распакованного архива contrib:
mkdir build cd build cmake -D CMAKE_BUILD_TYPE=RELEASE \ -D CMAKE_INSTALL_PREFIX=/usr/local \ -D INSTALL_PYTHON_EXAMPLES=ON \ -D OPENCV_EXTRA_MODULES_PATH=~/opencv/opencv_contrib-3.4.0/modules \ -D BUILD_EXAMPLES=ON ..
В случае успешной сборки увидим следующее. На данный момент мы всего лишь выполнили все условия для компиляции инсталлятора OpenCV, поэтому обратите внимание на секцию Python3 (или Python2) она должна быть как на скриншоте, в ином случае (или в случае фейла) проверьте:
  • возможно во время сборки не было активировано виртуальное окружение (cv) - workon cv
  • Еще возможная причина фейла: неверный абсолютный путь к папке дополнительных модулей contrib
  • На крайний случай можно проверить текущую директорию - вы должны находиться в папке build распакованного архива OpenCV выбранной версии
  • Напоследок убедиться, что версии релизов основного и contrib пакетов совпадают
В любом случае ничего страшного) Следует все перепроверить и запустить сборку заново
Если сборка прошла гладко, значит все условия для компиляции инсталлятора OpenCV удовлетворены и мы сейчас соберем из исходников собственный свежий стабильный дистрибутив OpenCV с extra-модулями!
Запускаем компиляцию
Параметр -j4 означает количество задействованных ядер процессора, у Raspberry Pi 3 их 4.
ВНИМАНИЕ!! Этот процесс в лучшем случае займет порядка 1,5 часов времени!!!
make -j4
Если наблюдаем краш в первые 5 минут компиляции, это вполне может произойти даже при идеальных условиях, то сбрасываем результат и запускаем компиляцию на одном ядре:
make clean make
В случае успеха увидим следующее - процесс компиляции завершен на 100%
Остается запустить собранный инсталлятор командой
sudo make install sudo ldconfig
Все, OpenCV установлен на Raspberry! Для удобного его использования дело остается за малым - пробросить на OpenCV в созданное виртуальное окружение Питона (cv). Определим директорию - так как OpenCV - это библиотека Питона, то должна находиться в папке остальных библиотек, проверим:
  • команда ls выводит в терминал содержимое указанной директории
  • не забудьте указать в команде папку Python с версией, для которой собственно устанавливали OpenCV
ls /usr/local/lib/python3.5/site-packages/
В исключительных случаях библиотека может находиться в соседней папке dist-packages :
ls /usr/local/lib/python3.5/dist-packages/
Перейдем в эту директорию
cd /usr/local/lib/python3.5/site-packages/
Переименуем файл библиотеки - так будет проще вызывать ее в коде Python
sudo mv cv2.cpython-35m-arm-linux-gnueabihf.so cv2.so
Скопируем полный путь к файлу.

Перейдем в каталог библиотек виртуального окружения cv:
cd ~/.virtualenvs/cv/lib/python3.5/site-packages/
Создадим здесь симлинк на OpenCV:
ln -s /usr/local/lib/python3.5/site-packages/cv2.so cv2.so
Проверим результат командой ls:

Проверка

Откроем новое окно терминала
source ~/.profile workon cv python import cv2 cv2.__version__
Если все сделано правильно, то в консоли Питона библиотека OpenCV импортируется без ошибок

В случае ошибки импортирования внимательно проверьте правильность переименовывания файла библиотеки и создание симлинка на него (расширение - .so), а также успешность перехода в виртуальное окружение cv