You have a phone, Termux, and a script that imports cv2 — and pip will not give you OpenCV. The pip route downloads OpenCV's source and starts a compile that stops in CMake, looking for an Android SDK that does not exist inside Termux. You do not need any of it: the Termux repositories ship OpenCV and NumPy as prebuilt packages, and a few commands install them. This guide shows why pip fails, the exact commands that work, how to verify the import and the pixel buffers with real numbers, and where the script goes once the phone has proved it.
Why does pip install opencv-python fail in Termux?
pip fails in Termux because no opencv-python wheel on the Python Package Index matches Termux's Bionic-based Python. So pip falls back to a 90.3 MB source tarball — 4.6.0.66 in one logged run — and starts compiling OpenCV on the phone.
The wheels on the package index are built for glibc-based Linux. Termux's Python is compiled against Android's Bionic libc, the wheel tag never matches, and pip does the only thing left: it downloads the source distribution and builds it on the device. The log shows the turn immediately:
Collecting opencv_python
Using cached opencv-python-4.6.0.66.tar.gz (90.3 MB)
That archive is OpenCV's full source, and pip needs NumPy first — which has no matching wheel either, so a second on-device compile starts. The tooling arrives with pkg install cmake ninja. Then configure stops on the error that ends every attempt: CMake asks for the Android SDK location through ANDROID_SDK_ROOT, ANDROID_HOME or ANDROID_SDK. Termux contains no Android SDK and no Java toolchain, so there is no path to give it. The same CMake search-path and target questions decide any cross-build of OpenCV; CMake paths and targets in OpenCV builds goes deeper on that configuration step.
Which Termux package should you install instead?
Install the repository packages instead: pkg install x11-repo adds the extra repository, and pkg install opencv python-numpy puts a compiled-for-Android OpenCV and its NumPy dependency on the phone with no compiler, no SDK and no source build.
Both packages are built by the Termux maintainers for this exact environment: the library against Termux's own Python, and NumPy as the package python-numpy. The repository layout has drifted between releases. You will see the OpenCV package named opencv, opencv-python or python-opencv-python depending on the snapshot your mirror serves; run pkg search opencv and install what it lists. One rule does not move: NumPy comes from pkg, not pip — the documented guidance is to use the purpose-built python-numpy package rather than pip-installing NumPy.
How do you install OpenCV in Termux step by step?
Four commands do the whole job: pkg update, pkg install python, pkg install x11-repo and pkg install opencv python-numpy, run in that order, and you have an importable cv2 in minutes on a normal connection.
- Refresh the package index with
pkg update, and takepkg upgradewhen it is offered, so the repository metadata and the installed base agree. - Install Python 3 with
pkg install python. Termux builds it against Android's Bionic libc; one logged phone carried Python 3.10.7. - Add the extra repository with
pkg install x11-repo. It carries the OpenCV package. - Install the libraries with
pkg install opencv python-numpy. If the name has moved on your mirror's snapshot,pkg search opencvprints the current one. - Verify before you write any code — the import check in the next section is the gate.
- From here on, keep pip for pure-Python packages only. Anything that ships compiled code belongs to pkg.
How do you verify the install works on a real image?
Verify in two moves: the one-liner python3 -c "import cv2; print(cv2.__version__)" proves the library loads, then a three-line script on a real image proves imread, cvtColor and the pixel buffers behave.
import cv2 # cv2 from the pkg build
img = cv2.imread("part.jpg") # BGR uint8, or None if the path is unreadable
print(img.shape) # (480, 640, 3) for a 640 x 480 colour file
grey = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
print(grey.shape, grey.dtype) # (480, 640) uint8
The names img and grey are illustrative; cv2.imread, cv2.cvtColor and cv2.COLOR_BGR2GRAY are OpenCV's documented API. An unreadable path makes imread return None, and the next call throws — so check the frame before processing it. If the file lives in shared storage, grant Termux storage access in Android's settings, or keep test images inside Termux's own home directory. The empty-frame failure mode has its own walkthrough in cv2 imwrite assertion failed: fix the frame first, and capture options for camera modules are covered in camera module image acquisition without saving files.
Then size the data your loop has to move:
The last line decides whether per-frame work fits a 30 fps loop, if that is your target rate: every Python-level pass over a 921,600-byte buffer spends milliseconds you may not have, which is why vectorised cv2 calls beat nested loops on the phone.
When is a from-source CMake build worth the trouble?
Almost never: a from-source build makes sense only if you need a version or a contrib module the repository does not ship. It costs an on-phone CMake build that runs to hours even with the Android and Java targets switched off.
If you do go down that road: pkg install cmake ninja, fetch the OpenCV source, and configure with everything Termux cannot satisfy switched off. The working attempt on record used cmake ../opencv -DBUILD_JAVA=OFF -DBUILD_ANDROID_EXAMPLES=OFF, with Termux's clang (Clang 14.0.6 in that log) as the compiler. Configure passed the SDK error only once the Android and Java targets were out of the project. Budget hours of compile time on a phone SoC, and expect a private build you maintain yourself. Check what you actually need first: for a contrib module such as ArUco, test hasattr(cv2, "aruco") before committing. Note that a self-built cv2 is also how version conflicts between tools start — OpenCV version conflicts that crash vision calibration tools shows the failure pattern.
How do you move the working script onto production hardware?
Keep the cv2 code and swap the frame source: in production the frames arrive from the camera SDK as buffers you wrap into NumPy arrays, so your threshold-and-measure logic runs unchanged on a board-level camera driven by a vision controller.
A phone proves the algorithm, not the station: it has no trigger input, no strobe control and no repeatable exposure, and it throttles long before a shift ends. The port is small because the cv2 layer stays. Production code takes each frame from the camera SDK and wraps the buffer in a Mat without copying; everything downstream runs as it did on the phone. Plan the move with board level camera selection for embedded vision machines and the board camera evaluation checklist for inspection systems. Settle the module's wiring question early with camera module interface compatibility: what to verify.
For a bench that runs these scripts, the pattern is a global-shutter board camera feeding an entry vision controller:
- Sensor format
- 1/1.8"
- Lens mount
- C-mount
- Sensor format
- 1/2.9"
- Lens mount
- M12
LS-BCM-0003 pairs a 1/1.8" global-shutter IMX178 sensor with USB3 output at 120 fps. MV-CB016-10GM-M-W stays smaller: a 1.6 MP global-shutter mono sensor behind an M12 mount on GigE. The controller half:
- LAN ports
- 3-4 LAN ports
- USB 3 ports
- 2 USB 3 ports
- Light outputs
- 4 built-in channels
- Memory
- 8 GB
The MV-VC2140-128G40-1T brings 8 GB of memory, 4 built-in light channels for strobe control and an Intel N-series processor — the trigger and light plumbing the phone never had. Pick the sensor from the board-level cameras range and the compute from vision controllers; the camera configurator and the camera finder narrow both by resolution, shutter and interface. The repo-package habit carries over to that hardware too: on an embedded vision host, OpenCV still comes from the platform's package repository, as in installing packages into a JetPack target filesystem.
Which mistakes cost the most time?
Two mistakes dominate the wasted hours: pip-installing NumPy over the repository build, and exporting ANDROID_SDK_ROOT to appease CMake — the first duplicates a package you already have, the second points a build at an SDK Termux never had.
-
pip install numpy. It starts a second on-device compile of a library pkg already provides aspython-numpy, and the pip copy can shadow the repository build at import time. -
Exporting
ANDROID_SDK_ROOT. No Android SDK exists inside Termux; the variable only changes which missing path the CMake error names. Either skip that build or switch the Android targets off in your own CMake project. -
Switching to
opencv-python-headless. Headless drops the GUI code, not the native core — the wheel mismatch and the CMake failure are identical. -
Trusting
imshowtoo early. The import test needs no display, and window calls depend on your Termux GUI set-up; prove the pipeline withcv2.imwriteto a PNG you can pull off the phone first.
Once the import prints a version and the three-line script processes a real image, the phone has done its job. The same code then runs on bench hardware where trigger, strobe and exposure sit under your control. More bring-up and integration walkthroughs sit on the systems topic page, and if the open question is hardware rather than code, send the part, the defect and the cycle time through the contact page — we can size the camera and controller to the script you have proven.
Questions
Does pip install opencv-python-headless work in Termux?
No. Headless drops only the GUI wrapper; the native core is the same code. pip still finds no matching wheel and still stops in CMake at the Android SDK error. The repository package already covers headless use: run your scripts on image files and skip window calls entirely, and no display stack is needed.
Do virtual environments see the pkg-installed OpenCV?
Only if the venv is created with the system site-packages included. pkg packages install into the system interpreter's site-packages, and an isolated venv starts without them. Create yours with the system-site-packages option, or prototype against the system Python and keep pip's pure-Python extras inside the venv.
Can cv2.VideoCapture(0) open the phone's camera in Termux?
Not out of the box. The repository build has no bridge to Android's camera stack, so index 0 does not give you the phone sensor. Capture stills or clips with the phone's normal camera app, copy the files into Termux-accessible storage, and run your script on files — which is also the more repeatable way to tune parameters.
How long does the pkg route take next to pip?
The pkg route downloads prebuilt binaries and finishes in minutes on a normal connection. The pip route downloads a 90.3 MB source archive, builds NumPy first, then OpenCV. On a phone that is hours of compile time — often ending in the CMake Android SDK error with nothing installed at the end of it.
Which hardware runs these scripts once the prototype works?
The cv2 code carries over; only the capture wrapper changes. Choose the interface by the bench: GigE board cameras tolerate cable runs to about 100 m, while USB3 suits short runs where you want high frame rates. For that second case the LS-BCM-0003 prints 120 fps in its data. Wrap each SDK frame as a NumPy array and the rest runs unchanged.


