专栏简介 | ||
💒个人主页 📰专栏目录 点击上方查看更多内容 | 📖心灵鸡汤📖 我们唯一拥有的就是今天,唯一能把握的也是今天 建议把本文当作笔记来看,据说专栏目录里面有相应视频🤫 | 🧭文章导航🧭 ⬆️ 15.Core之广义矩阵乘法运算 ⬇️ 16.Core之图像连接 |
Core之图像基础变换
基础变换操作汇总
一、翻转
1.flip
围绕垂直、水平或两个轴翻转2D数组
flip(Mat src, Mat dst, int flipCode) | |
参数: | |
src | 输入数组 |
dst | 输出数组的大小和类型与源(src)相同 |
flipCode | 一个标志,用于指定如何翻转数组。0 表示围绕 x 轴翻转,正数(例如 1)表示围绕 y 轴翻转,负数(例如 -1)表示同时围绕 x 和 y 轴翻转 |
Mat src = Imgcodecs.imread("flip.jpg");
// 创建一个与原始图像相同大小和类型的目标图像
Mat dst = new Mat(src.rows(), src.cols(), src.type());
// 进行水平翻转
Core.flip(src, dst, 1);
// 保存翻转后的图像
Imgcodecs.imwrite("res_flip.jpg", dst);
结果:
2.flipND
在给定的轴上翻转n维数组。下方参数的解释仅对二维矩阵进行说明
flipND(Mat src, Mat dst, int axis) | |
参数: | |
src | 输入数组 |
dst | 输出数组的大小和类型与源(src)相同 |
axis | 与flip类似沿轴翻转,0 表示沿x轴,1表示沿y轴翻转。不同的是 -1仅翻转y轴 |
Mat mat = new Mat(3, 3, CvType.CV_8UC1);
mat.put(0,0,1,2,3,4,5,6,7,8,9);
Mat dst = new Mat();
Core.flipND(mat,dst,-1);
请自行验证结果
二、旋转
以90度的倍数旋转矩阵.(中心旋转
)
1.字段
ROTATE_180 | 将图像旋转180度 |
ROTATE_90_CLOCKWISE | 将图像顺时针旋转90度 |
ROTATE_90_COUNTERCLOCKWISE | 将图像逆时针旋转90度 |
2.rotate
rotate(Mat src, Mat dst, int rotateCode) | |
参数: | |
src | 输入矩阵 |
dst | 输出矩阵 |
rotateCode | 旋转标识。ROTATE_* |
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat imread = Imgcodecs.imread("flip.jpg");
Mat dst = new Mat();
Core.rotate(imread,dst,Core.ROTATE_180);
HighGui.imshow("imread",imread);
HighGui.imshow("dst",dst);
HighGui.waitKey();
结果:
三、转置
对矩阵进行行列互换。与Mat.t()方法作用一样。
1.transpose
transpose(Mat src, Mat dst) | |
参数: | |
src | 输入矩阵 |
dst | 输出矩阵 |
Mat imread = Imgcodecs.imread("flip.jpg");
Mat dst = new Mat();
Core.transpose(imread,dst);
HighGui.imshow("imread",imread);
HighGui.imshow("dst",dst);
HighGui.waitKey();
结果:
2.transposeND
适用于 n 维矩阵的转置.。下方参数的解释仅对二维矩阵进行说明.
了解即可
注意: 输入应为连续的单通道矩阵
transposeND(Mat src, MatOfInt order, Mat dst) | |
参数: | |
src | 输入矩阵 |
order | [0,1,..,N-1] 的排列,其中 N 是 src 的轴数。dst 的第 i 个轴将对应输入的 order[i] 轴 |
dst | 输出矩阵 |
Mat mat = new Mat(3, 3, CvType.CV_8UC1);
mat.put(0,0,1,2,3,4,5,6,7,8,9 );
Mat dst = new Mat();
MatOfInt matOfInt = new MatOfInt();
//y轴和x轴互换
matOfInt.fromArray(1,0);
Core.transposeND(mat,matOfInt,dst);
四、复制
1.completeSymm
1.将一个方阵的下半部分或上半部分复制到其另一半。矩阵的对角线保持不变。
completeSymm(Mat m, boolean lowerToUpper) | |
参数: | |
m | 输入(输出)矩阵,矩阵必须为方矩阵 |
lowerToUpper | 如果为 true,则将下半部分复制到上半部分。否则,将上半部分复制到下半部分 |
Mat mat = new Mat(3, 3, CvType.CV_8UC1);
mat.put(0,0,1,2,3,4,5,6,7,8,9 );
Core.completeSymm(mat,true);
请自行验证
2.repeat(重复复制)
每个轴上重复输入数组一次或多次。
repeat(Mat src, int ny, int nx, Mat dst) | |
参数: | |
src | 输入矩阵 |
ny | 沿y轴复制次数 |
nx | 沿x轴复制次数 |
dst | 输出数组,类型应与输入数组src相同 |
Mat imread = Imgcodecs.imread("flip.jpg");
Mat dst = new Mat();
Core.repeat(imread,2,2,dst);
结果:
五、缩放
1.convertScaleAbs
缩放、计算绝对值,并将结果转换为8位
convertScaleAbs(Mat src, Mat dst, double alpha, double beta) | |
参数: | |
src | 输入矩阵 |
dst | 输出矩阵,大小和类型与输入数组相同 |
alpha | 缩放因子 |
beta | 偏移量 |
Mat src = Mat.eye(3, 3, CvType.CV_32F);
src.put(0,0,1,2,3,4,5,6,7,8,9);
System.out.println("src.dump() = \n" + src.dump());
// 创建输出矩阵
Mat dst = new Mat();
// 设置缩放因子和偏移量
double alpha = 2.0;
double beta = 1.0;
// 调用convertScaleAbs方法进行缩放、取绝对值和转换
Core.convertScaleAbs(src, dst, alpha, beta);
System.out.println("dst.dump() = \n" + dst.dump());
请自行验证结果
通过结果,可以看出我们可以用这个函数改变图像的亮度。
窗口示例:
public static void main(String[] args) {
// 加载OpenCV库
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat imread = Imgcodecs.imread("flip.jpg");
JFrame frame = HighGui.createJFrame("img", HighGui.WINDOW_NORMAL);
JPanel jPanel = new JPanel();
jPanel.setLayout(new BoxLayout(jPanel,BoxLayout.Y_AXIS));
JSlider slider = new JSlider(0,10,1);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.setMajorTickSpacing(10);
slider.setMinorTickSpacing(1);
JSlider slider2 = new JSlider(0,100,10);
slider2.setPaintTicks(true);
slider2.setPaintLabels(true);
slider2.setMajorTickSpacing(10);
slider2.setMinorTickSpacing(1);
jPanel.add(slider);
jPanel.add(slider2);
// 创建输出矩阵
Mat dst = new Mat();
frame.add(jPanel,BorderLayout.NORTH);
JLabel jLabel = new JLabel();
Image image = HighGui.toBufferedImage(imread);
jLabel.setIcon(new ImageIcon(image));
frame.add(jLabel,BorderLayout.CENTER);
final int[] alpha = {1};
final int[] beta = {0};
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
JSlider source = (JSlider) e.getSource();
alpha[0] =source.getValue();
Core.convertScaleAbs(imread, dst, alpha[0], beta[0]);
Image image1 = HighGui.toBufferedImage(dst);
jLabel.setIcon(new ImageIcon(image1));
frame.repaint();
}
});
slider2.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
JSlider source = (JSlider) e.getSource();
beta[0] = source.getValue();
System.out.println("beta[0] = " + beta[0]);
Core.convertScaleAbs(imread, dst, alpha[0], beta[0]);
Image image1 = HighGui.toBufferedImage(dst);
jLabel.setIcon(new ImageIcon(image1));
frame.repaint();
}
});
frame.pack();
frame.setVisible(true);
}
结果:
六、加边框
在图像的边界周围添加边框
1.字段
只列举了部分
BORDER_CONSTANT | 在图像边界上填充一个常数值 |
BORDER_REPLICATE | 边界像素的值被复制到图像外部 |
BORDER_REFLECT | 边界像素的值通过反射方式复制到图像外部 |
BORDER_REFLECT | 当访问超出原始图像边界的像素时,使用环绕的方式从另一侧复制像素值。(在水平方向上,右侧的像素值从左侧复制,反之亦然。在垂直方向上,上方的像素值从下方复制,反之亦然) |
BORDER_TRANSPARENT | 边界之外的像素值为0(黑色) |
2.方法介绍
该函数将源图像复制到目标图像的中间。复制的源图像左侧、右侧、上方和下方的区域将用外推像素填充
copyMakeBorder(Mat src, Mat dst, int top, int bottom, int left, int right, int borderType, Scalar value) | |
参数: | |
src | 源图 |
dst | 与src类型相同且大小为(src.cols+left+right, src.rows+top+bottom)的目标图像 |
top | 顶部像素 |
bottom | 底部像素 |
left | 左部像素 |
right | 右部像素 |
borderType | 边界类型,BORDER_* |
value | 如果 borderType 是 BORDER_CONSTANT,则此参数指定边框的颜色 |
Mat src = Imgcodecs.imread("flip.jpg");
//频域图像
Mat dst = new Mat();
Core.copyMakeBorder(src,dst,100,100,100,100,Core.BORDER_REPLICATE);
结果:
请尝试其它类型查看效果