Spark Java 用 KMeans算法实现图片压缩
来源:互联网 发布:剑三咩太捏脸数据 编辑:程序博客网 时间:2024/05/16 11:59
压缩前:981 KB
压缩后:111 KB
思路:
取得图片每一点的像素,组成向量Vector如下:(w,h,R,G,B);
设置目的K值,训练所有点,获得KMeansModel;
此遍历所有的点,利用模型预测每个点属于哪个 中心点,同时改变这个点的R,G,B值使这个点的颜色 与这个点所在的集合相同;
重新利用收集的数据画出图片。
一共需要两个类,一个处理跟图片相关,一个处理KMeans算法,好像pytho语言写就好简单,哎。
处理图片类如下:
import java.awt.Color; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream;import java.util.ArrayList;import java.util.List;import javax.imageio.ImageIO;import scala.Tuple3; public class AnalyzePicture { /** * * @param oldFilePath:你想压缩的图片的地址 * @param newFilePath:压缩后存放的地址 * @param t:tuple类型(scala里面的,因为在学习spark所以就拿来用),<Integer,Integer,Integer>-><weight,high,RGB> */ public static void generatePhoto(String oldFilePath,String newFilePath,List<Tuple3<Integer,Integer,Integer>>t) { try{ BufferedImage imgOld = ImageIO.read(new File(oldFilePath)); int w=imgOld.getWidth(); int h=imgOld.getHeight(); File out = new File(newFilePath); if (!out.exists()) out.createNewFile(); OutputStream output = new FileOutputStream(out); BufferedImage imgOut = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR); for(Tuple3<Integer,Integer,Integer> tt:t) { imgOut.setRGB( tt._1(), tt._2(),tt._3()); } ImageIO.write(imgOut, "png", output); output.close(); }catch(Exception e) { e.printStackTrace(); } } /** * 作用是返回图片每一点的RGP值 * @param filePath :想要处理的图片的地址 * @return String: with,high,R,G,P,这里我把RGP独立成三个方向的值 */ public static List<String> getImageGRBStr(String filePath) { File file = new File(filePath); List<String>list=new ArrayList<String>(); if (!file.exists()) { return null; } try { BufferedImage bufImg = ImageIO.read(file); int height = bufImg.getHeight(); int width = bufImg.getWidth(); for (int i = bufImg.getMinX(); i < width; i++) { for (int j = bufImg.getMinY(); j < height; j++) { String str=i+","+j+","+((bufImg.getRGB(i, j) & 0xff0000) >> 16)+","+((bufImg.getRGB(i, j) & 0xff00) >> 8)+","+((bufImg.getRGB(i, j) & 0xff)); list.add(str); } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return list; }}
KMeans算法类如下:
import java.util.ArrayList;import java.util.List;import org.apache.log4j.Level;import org.apache.log4j.Logger;import org.apache.spark.api.java.JavaRDD;import org.apache.spark.api.java.JavaSparkContext;import org.apache.spark.api.java.function.Function;import org.apache.spark.mllib.clustering.KMeans;import org.apache.spark.mllib.clustering.KMeansModel;import org.apache.spark.mllib.linalg.Vector;import org.apache.spark.mllib.linalg.Vectors;import org.apache.spark.rdd.RDD;import org.apache.spark.sql.SparkSession;import scala.Tuple3;public class PhotoKMeans { public static void main(String[]args) { //屏幕spark多余的log Logger.getLogger("org.apache.spark").setLevel(Level.WARN); Logger.getLogger("org.apache.spark").setLevel(Level.OFF); //获取到到了图片的每个点的情况String->w,h,R,G,P List<String>list=AnalyzePicture.getImageGRBStr(args[0]); //设置spark为本地模式,这样就不要老是跑到linux集群上去跑了 SparkSession spark=SparkSession.builder().master("local").appName("PhotoKMeans").getOrCreate(); //目的,初始化非file的数据源 JavaSparkContext javaSpark=new JavaSparkContext(spark.sparkContext()); //首先把List<String>变成RDD<String>,RDD中的String为"w,h,R,G,P",去除","之后,RDD中的String映射为向量 {w,h,R,G,P} RDD<Vector>rdd=javaSpark.parallelize(list).map(new StringToVector(",")).rdd().cache(); KMeansModel model=KMeans.train(rdd, Integer.parseInt(args[2]), Integer.parseInt(args[3]));//拿去处理 //获得处理后的中心向量 Vector[]vectors=model.clusterCenters(); //获得图片所有点的向量 ,为了下面获取每个点属于哪个中心点而准备 List<Vector>points=rdd.toJavaRDD().collect(); //存储重新调整之后图片每个点的w,h,RGP List<Tuple3<Integer,Integer,Integer>>tuple=new ArrayList<Tuple3<Integer,Integer,Integer>>(); for(Vector v:points) { int cluster=model.predict(v);//start from 0 double[]rgbs=vectors[cluster].toArray(); double[]x=v.toArray(); int ww=(int)x[0]; int hh=(int)x[1]; int rgb=((int) rgbs[2]<<16)+((int) rgbs[3]<<8)+((int) rgbs[4]);//这里是将R,G,P变成RGP Tuple3<Integer,Integer,Integer>t=new Tuple3<>(ww,hh,rgb); tuple.add(t); } //交给处理类生成新的图片 AnalyzePicture.generatePhoto(args[0], args[1], tuple); } public static class StringToVector implements Function<String,Vector> { String target=""; public StringToVector(String target) { this.target=target; } @Override public Vector call(String a) throws Exception { // TODO Auto-generated method stub String[]aa=a.split(target); double[]aaa=new double[aa.length]; for(int i=0;i<aa.length;i++) { aaa[i]=Double.parseDouble(aa[i]); } return Vectors.dense(aaa); } }}
最用调用KMeans类,参数如下:
args[0] =你想处理的图片地址
args[1] =处理后新图片的地址
args[2] =K值(K越大图片越逼真)
args[3] =允许的最大迭代次数
C:/Users/Administrator/Pictures/fengjing.png C:/Users/Administrator/Pictures/2_564.png 600 5
阅读全文
1 0
- Spark Java 用 KMeans算法实现图片压缩
- Spark:Scala实现KMeans算法
- kmeans算法java实现
- Java实现Kmeans算法
- kMeans算法JAVA实现
- Kmeans算法java实现
- spark利用MLlib实现kmeans算法实例
- spark下实现并行kmeans算法
- K-Means及Spark实现Kmeans算法
- kmeans算法的java实现
- Java实现聚类分析Kmeans算法
- Spark上实现Kmeans
- 用Hadoop实现KMeans算法
- Hadoop/MapReduce 及 Spark KMeans聚类算法实现
- 聚类算法之KMeans(Java实现)
- 聚类算法之KMeans(Java实现)
- 聚类算法之KMeans(Java实现)
- 聚类算法之KMeans(Java实现)
- StandardSetController クラス
- Android学习笔记5---四大组件之Activity
- 有分号;隔开的字符串的拆分,合并,读取
- 注解(Annotation)自定义注解入门
- C# dataTable的linq联合查询,插入到新的dataTable中
- Spark Java 用 KMeans算法实现图片压缩
- jQuery动态添加.active 实现导航l栏效果
- ASCII码排序
- php swoole 异步处理任务例子
- 萌新入门的学习心得-信息安全出入门
- Spark配置参数详解
- NP是可计算的吗?- “算法”的二个层次
- pthread_attr_t 线程属性
- 欢迎使用CSDN-markdown编辑器