暑假复习篇之图像识别①
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}//重写的窗体自身会调用的刷新绘制方法@Overridepublic 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【动态初始化】:跟一维数组一样,先声明,在定义