1、图片比较:图片信息的相似码比较,比较图片中像素的数量 顺序等
2、图片物体识别:AI及其学习图片搜索:使用卷积运算,搭建CNN卷积神经网络,提取特征,根据特征数值进行比较,根据特征分布做到图片识别【难】
一、预备知识:
①读取图片的像素值
②可以操作二维数组
③缩小图片
④对于图片的像素进行逐个处理 灰度 二值化
⑤有字符串操作的基础
二、步骤
1、Python 爬虫准备好一千张照片:一千张类似的照片 或者 一千张不同的照片
2、完成一张照片的处理
①使用FIle类+ImageIO类 读取图片的像素 存入到一个BufferedImage 对象中
②将BufferedImage图片对象 中的像素存入一个int类型的二维数组中
③将图片进行缩小 可缩小到8*8 / 16*16 / 32*32 / 64*64 / 128*128 这几个规格
④对像素进行灰度处理
⑤然后根据灰度值进行二值化判断,一个像素如果是黑色,设定为字符1 否则就是字符0
⑥拼接所有的01字符串
三、代码示例
package daytoday.lfx250708;
import javax.swing.*;
import java.awt.*;
public class ImageUI extends JFrame {
ImageProcess ip = new ImageProcess();
//在方法中使用继承到的方法 设置窗体的属性
public ImageUI() {
super("图片处理");
setLocationRelativeTo( null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 600);
setVisible(true);
ip.g = getGraphics();//获取继承的画笔对象传给绘制图形处理对象的g
}
//重写的窗体自身会调用的刷新绘制方法
@Override
public void paint(Graphics g) {
super.paint(g);//调用父类原本的刷新方法
//调用读取图片的方法
int[][] imgArr = ip.getImageArr("C:\\Users\\lfx\\Desktop\\1.png");
ip.processImage(imgArr);
}
public static void main(String[] args) {
new ImageUI();
}
}
package daytoday.lfx250708;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class ImageProcess {
Graphics g;//图形类 可以用来绘制单个像素点
//1、读取图片的像素值
public int[][] getImageArr(String Path){
File file = new File(Path);
try {
BufferedImage img = ImageIO.read( file);
int w = img.getWidth();
int h = img.getHeight();
int[][] imgArr = new int[w][h];
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
imgArr[i][j] = img.getRGB(i,j);
}
}
return imgArr;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//2、将图片对应的二维数组进行缩小
public void processImage(int[][] imgArr){
int w = imgArr.length;
int h = imgArr[0].length;
//原图绘制
for (int i = 0; i < w; i++){
for (int j = 0; j < h; j++){
int pixNum = imgArr[i][j];//循环中遍历取出每个像素值
//封装像素值到color中
Color color = new Color(pixNum);
this.g.setColor( color);
this.g.fillRect(100 + i,200 + j,1,1);
}
}
}
//3、灰度
//4、二值化
}
四、知识点复习
1、数组复习【数组是引用类型】【任何数组的本质都是一维数组】
一维数组:
- 数组定义格式1【动态初始化】:数据类型[ ] 数组名 = new 数据类型[大小]
- 格式2【动态初始化】: 先声明数组 数据类型[ ] 数组名;在创建数组 数组名 = new 数据类型[ 大小 ];
- 格式3【静态初始化】:数据类型[ ] 数组名 = {元素值,元素值……}
- 数组的引用:数组名[下标 / 索引]
- 数组赋值:数组在默认情况下是引用传递,赋的值是地址 基本数据类型赋值,赋值方式值拷贝。
运行结果:
- 数组拷贝:首先要给新的数组开辟一个空间,然后对老数组进行遍历将老数组的值赋值给新数组
- 数组反转
//数组反转 public class ArrExercise { public static void main(String[] args) { int[] arr1 = {11,22,33,44,55,66}; int[] arr2 = new int[arr1.length]; for (int i = 0;i < arr1.length;i++){ arr2[i] = arr1[arr1.length - 1 - i]; } arr1 = arr2; System.out.println("===arr1的值==="); for (int i = 0;i < arr1.length;i++){ System.out.print(arr1[i] + " "); } } }
- 用户在数组上面添加值
public class ArrExercise {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] arr = {1,2,3,4,5,6,7,8,9};
do {
int[] arrNew = new int[arr.length + 1];
for (int i = 0; i < arr.length; i++) {
arrNew[i] = arr[i];
}
System.out.println("请输入你要添加的元素");
int addNum = sc.nextInt();
arrNew[arrNew.length - 1] = addNum;
arr = arrNew;
System.out.println("===ArrNew数组值===");
for (int i = 0; i < arrNew.length; i++) {
System.out.println(arrNew[i]);
}
//问用户是否需要继续添加
System.out.println("是否继续添加 y/n");
char key = sc.next().charAt(0);
if (key == 'n'){
break;
}
}while (true);
}
}
- 排序分类:内部排序:将需要处理的所有数据都加载到内部存储器重进行排序【交换排序法、选择式排序法和插入式排序法】,外部排序:数据量过大,无法全部加载到内存中,需要借助外部内存进行排序【合并排序法和直接合并排序法】
- 冒泡排序特点【假设数组为【24,69,80,57,13】】
①一共有五个元素
②一共进行四轮排序,可以看成是外层循环
③每一轮顺序可以确定一个数的位置,比如第一轮确定最大数,第二轮确定第二大数的位置
④当进行比较时,如果前面的数大于后面的数,就进行交换
⑤每轮都在减少4->3->2->1
//冒泡排序代码示例
public class ArrExercise {
public static void main(String[] args) {
//数组为【24,69,80,57,13]
int[] arr = {24,69,80,57,13};
int temp = 0; //中间变量
//利用嵌套for循环进行排序
for (int i = 0; i < arr.length - 1; i++){
for (int j = 0; j < arr.length - 1 - i; j++){
if (arr[j] > arr[j + 1]){
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
System.out.println("===冒泡排序后的数组===");
for (int i = 0; i < arr.length; i++){
System.out.print(arr[i] + " ");
}
}
}
- 查找:顺序查找 和 二分查找 【下面是顺序查找的代码示例】
public class ArrExercise {
public static void main(String[] args) {
//用户输入一个字符串与数组中的字符串进行匹配 并输出该字符串在数组中的下标
String[] name = {"张三","李四","王五","赵六","小七"};
Scanner sc = new Scanner(System.in);
System.out.println("请输入名字");
String name1 = sc.next();
for (int i = 0; i < name.length; i++) {
if (name[i].equals(name1)){
System.out.println("恭喜你找到" + name1 + "的下标为" + i);
break;
}else if (i == name.length - 1){
System.out.println("没有找到" + name1);
}
}
}
}
二维数组:
- 二维数组的使用:格式1【动态初始化】:类型[ ][ ] 数组名 = new 类型[大小][大小]【第一个括号代表有多少个一维数组】
- 二维数组在内存的存在形式
- 格式2【动态初始化】:跟一维数组一样,先声明,在定义