git config --global http.postBuffer 2024288000
git config --list
git config --global core.compression 0
git clone --depth 1 https://mirrors.ustc.edu.cn/homebrew-core.git
git fetch --unshallow
git pull --all
3. 确保必须要装ANT
除非你不想用OpenCV Java,很多人生成不了以下这两个文件就是因为忘记装ant了。
brew install ant
装完后你一定要确保你的Mac的环境变量path里可以直接访问ant命令。
如果不可以在任意地方运行ant -version命令得到ant的正确输出,你还需要手工自己在~/.bash_profile里加入ant的命令于你的path变量中去。
记得一定要是ant 1.9或者以上版本,否则装了也是白装。
4. 必须记得安装python3
这个梗和上面第3点,必装ANT一样。OpenCV无论是3还是4在安装时要生成Java这两个文件,必装Python3.
brew upgrade python3
mac一般自带python2,而big sur版本中装OpenCV都用的是OpenCV4,它要求必须安装python3.
因此我们可以升级我们的本地python2至3,升级完后你原有的python2还会留着。网上会说把python3和python2互换一下。
但没必要,你可以保证python2和python3都存在。因为python2用的命令叫python,python3的命令叫python3.
这个没事的。因为我本机还有不少python2写的AI,因此我经常在两者间要用哪个时做手工切换。
5. 必须安装jdk
安装JDK17,对,你没看错。
最佳实践,在你的Mac上可以保持有jdk1.8同时还有jdk17.
现在的OpenCV无论是Windows10还是Mac下的编译安装,都会使用最新class version62版本即用的是jdk17去编译和生成的jar包。
因此同样,记得你的eclipse要用“2021-12”及以后的版本。因为在此之前的eclipse版本的compiled version只能认到jdk11最多13,因此到时你的eclipse如果不支持jdk17你在运行OpenCV的应用时,整个eclipse会因为“找不到jdk location“而最终卡死,卡到电脑CPU风扇转个不停,最后不得不”杀进程“。
然后启动eclipse用系统默认的jdk1.8,运行opencv项目用本机安装的jdk17来编译和运行以及debug。
非常重要,非常重要,非常重要,上面那句话用红色标出。
这是因为,jdk17做了巨大的改变,eclipse最新版可以认出jdk17但是eclipse最新版(目前的版本)用jdk17没法在Mac上运行(因为jdk17的jre目录里的内容已经变了)。
如果你用jdk17去做成了默认的系统级path变量,那么恭喜你,你的eclipse是启动不起来的。
因此我们才有了经常本机有3个以上jdk,其中低版本一个用运启动eclipse用。其它几个版本用于不同特性的工程用。
6. 开始安装OpenCV4
到此,你可以正式安装OpenCV4了。
OpenCV4的安装过程主要涉及到以下几个核心步骤,而在Mac下是一键完成的。Mac下烦是烦在上述的第1~第2步。即xcode command line以及brew update上,这两步过了后面是一帆风顺的。如果你是在Windows10或者是Linux下安装OpenCV,你就会体会到装OpenCV4时才是最痛苦的,而在Mac上,因为有了brew,因此从这一步开始你会觉得很Hi。
OpenCV安装核心步骤(供学习者知道OpenCV在编译安装时做了什么事)
- 下载OpenCV最新master源码;
- 下载OpenCV 对应版本的contribute源码包(有内置图形、JAVA包、声音等);
- 使用C编译器,生成C工程;
- 使用C编译器,编译C工程;
- 使用python3+ant对java文件进行编译并生成java通过jndi调用OpenCV的C的底层native lib包(在Windows10下是一个.dll文件);
- 把C编译生成成功的release包进行系统安装;
brew edit opencv
在安装前,你要确认你的opencv内的java编译选项是turn on的。默认opencv是不会安装和编译打包java文件的。
在控制端找到-DBUILD_opencv_java=OFF 修改为-DBUILD_opencv_java=ON ,如下图所示
那么你就可以:
brew install --build-from-source opencv
接下去按照我这个机型,22分钟后,一切显示failed 0,install successfully。
你就可以看到OpenCV4正确装在了你的这个路径下了
而java用文件是生成在这边的
使用OpenCV
将/usr/local/share/java/opencv4/libopencv_java454.dylib文件拷贝到jdk的lib目录下
然后新建一个Eclipse工程。
在Eclipse工程里记得对于OpenCV的工程要做如下的jvm设置。
然后在你的eclipse工程里放置一个叫ext-lib的目录,把opencv-454.jar包放在这个目录中然后使用工程的“add external JARs…“方式添加给到工程的classpath目录下。
我们书写第一个OpenCV应用,即读入一幅图片并用于展示用。
主程序-ImageShow.java
package org.mk.opencv;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
public class ImageShow {
public static void main(String[] args) {
// 载入dll或者lib包(必须先加载)
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// 将文件读入为OpenCV的Mat格式。注意测试时,路径不要包括中文
Mat src = Imgcodecs.imread("/Users/macuser/opt/img/ImageShow.jpg");
if (src.dataAddr() == 0) {
System.out.println("打开文件出错");
ImageViewer imageViewer = new ImageViewer(src, "第一幅图片");
imageViewer.imshow();
ImageViewer.java-用的是java swing的JFrame控件
package org.mk.opencv;
import org.mk.opencv.util.OpenCVUtil;
import org.opencv.core.Mat;
import javax.swing.*;
import java.awt.*;
public class ImageViewer {
private JLabel imageView;
private Mat image;
private String windowName;
* 如果使用junit测试时调用该方法,图像会一闪而过,可通过sleep()等方式暂时显示
* @param
private JFrame frame = null;
public ImageViewer() {
frame = createJFrame(windowName, 800, 600);
public ImageViewer(Mat image) {
this.image = image;
* @param image 要显示的mat
* @param windowName 窗口标题
public ImageViewer(Mat image, String windowName) {
frame = createJFrame(windowName, 1024, 768);
this.image = image;
this.windowName = windowName;
public void setTitle(String windowName) {
this.windowName = windowName;
public void setImage(Mat image) {
this.image = image;
* 图片显示
public void imshow() {
setSystemLookAndFeel();
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 用户点击窗口关闭
if (image != null) {
Image loadedImage = OpenCVUtil.matToImage(image);
// JFrame frame = createJFrame(windowName, image.width(), image.height());
imageView.setIcon(new ImageIcon(loadedImage));
frame.pack();
// frame.setLocationRelativeTo(null);
// frame.setVisible(true);
// frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 用户点击窗口关闭
private void setSystemLookAndFeel() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (UnsupportedLookAndFeelException e) {
e.printStackTrace();
private JFrame createJFrame(String windowName, int width, int height) {
JFrame frame = new JFrame(windowName);
imageView = new JLabel();
final JScrollPane imageScrollPane = new JScrollPane(imageView);
imageScrollPane.setPreferredSize(new Dimension(width, height));
frame.add(imageScrollPane, BorderLayout.CENTER);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
return frame;
OpenCVUtil.java工具包
package org.mk.opencv.util;
import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import javax.imageio.ImageIO;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import org.apache.log4j.Logger;
import org.mk.opencv.face.FaceRecogFromFiles;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.imgcodecs.Imgcodecs;
public class OpenCVUtil {
private static Logger logger = Logger.getLogger(OpenCVUtil.class);
public static Image matToImage(Mat matrix) {
int type = BufferedImage.TYPE_BYTE_GRAY;
if (matrix.channels() > 1) {
type = BufferedImage.TYPE_3BYTE_BGR;
int bufferSize = matrix.channels() * matrix.cols() * matrix.rows();
byte[] buffer = new byte[bufferSize];
matrix.get(0, 0, buffer); // 获取所有的像素点
BufferedImage image = new BufferedImage(matrix.cols(), matrix.rows(), type);
final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
System.arraycopy(buffer, 0, targetPixels, 0, buffer.length);
return image;
public static List<String> getFilesFromFolder(String folderPath) {
List<String> fileList = new ArrayList<String>();
File f = new File(folderPath);
if (f.isDirectory()) {
File[] files = f.listFiles();
for (File singleFile : files) {
fileList.add(singleFile.getPath());
return fileList;
public static String randomFileName() {
StringBuffer fn = new StringBuffer();
fn.append(System.currentTimeMillis()).append((int) (System.currentTimeMillis() % (10000 - 1) + 1))
.append(".jpg");
return fn.toString();
public static List<FileBean> getPicFromFolder(String rootPath) {
List<FileBean> fList = new ArrayList<FileBean>();
int fileNum = 0, folderNum = 0;
File file = new File(rootPath);
if (file.exists()) {
LinkedList<File> list = new LinkedList<File>();
File[] files = file.listFiles();
for (File file2 : files) {
if (file2.isDirectory()) {
// logger.info(">>>>>>文件夹:" + file2.getAbsolutePath());
list.add(file2);
folderNum++;
} else {
// logger.info(">>>>>>文件:" + file2.getAbsolutePath());
FileBean f = new FileBean();
String fileName = file2.getName();
String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
File fParent = new File(file2.getParent());
String parentFolderName = fParent.getName();
f.setFileFullPath(file2.getAbsolutePath());
f.setFileType(suffix);
f.setFolderName(parentFolderName);
fList.add(f);
fileNum++;
File temp_file;
while (!list.isEmpty()) {
temp_file = list.removeFirst();
files = temp_file.listFiles();
for (File file2 : files) {
if (file2.isDirectory()) {
// System.out.println("文件夹:" + file2.getAbsolutePath());
list.add(file2);
folderNum++;
} else {
// logger.info(">>>>>>文件:" + file2.getAbsolutePath());
FileBean f = new FileBean();
String fileName = file2.getName();
String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
File fParent = new File(file2.getParent());
String parentFolderName = fParent.getName();
f.setFileFullPath(file2.getAbsolutePath());
f.setFileType(suffix);
f.setFolderName(parentFolderName);
fList.add(f);
fileNum++;
} else {
logger.info(">>>>>>文件不存在!");
// logger.info(">>>>>>文件夹共有:" + folderNum + ",文件共有:" + fileNum);
return fList;
public static BufferedImage matToBufferedImage(Mat matrix) {
int cols = matrix.cols();
int rows = matrix.rows();
int elemSize = (int) matrix.elemSize();
byte[] data = new byte[cols * rows * elemSize];
int type;
matrix.get(0, 0, data);
switch (matrix.channels()) {
case 1:
type = BufferedImage.TYPE_BYTE_GRAY;
break;
case 3:
type = BufferedImage.TYPE_3BYTE_BGR;
// bgr to rgb
byte b;
for (int i = 0; i < data.length; i = i + 3) {
b = data[i];
data[i] = data[i + 2];
data[i + 2] = b;
break;
default:
return null;
BufferedImage image2 = new BufferedImage(cols, rows, type);
image2.getRaster().setDataElements(0, 0, cols, rows, data);
return image2;
public static Mat bufferedImageToMat(BufferedImage bi) {
Mat mat = new Mat(bi.getHeight(), bi.getWidth(), CvType.CV_8UC3);
byte[] data = ((DataBufferByte) bi.getRaster().getDataBuffer()).getData();
mat.put(0, 0, data);
return mat;
运行ImageShow.java后得到以下效果
结速本篇教程,下一篇我们讲如何在Windows10下安装OpenCV,这个过程比起Mac OS内安装OpenCV要痛苦百倍。
但是如果按照我的博客一步步走,100%会保证你不会出错,我趟过的那些血坑你们保证再也不会趟过。
OSError: [WinError 1455] 页面文件太小,无法完成操作。 Error loading “C:\ProgramData\Anaconda3\lib\site-packages\to
2022年5月20日
数据开源 | Magic Data开源基于ChatGPT的可扩展的对话数据集
2023年3月4日
人工智能专业计算机毕业设计选题推荐
2023年3月4日
毕业设计-基于机器视觉乒乓球分类捡球机器人的设计与实现 -OpenCV
2023年4月5日
yolov5训练可视化指标的含义
2023年3月26日