精华内容
下载资源
问答
  • 剧情提要: [机器小伟]在[工程师阿伟]的陪同下进入练气期第七层功法的修炼, 这次要修炼的目标是[条形统计图]。...今天[人叫板老师]提出了条形统计图的概念,小伟决定要好好地画一画。 小伟说
    剧情提要:
    [机器小伟]在[工程师阿伟]的陪同下进入练气期第七层功法的修炼,
    这次要修炼的目标是[条形统计图]。

    正剧开始:

    星历2016年01月26日 11:04:59, 银河系厄尔斯星球中华帝国江南行省。
    [工程师阿伟]正在和[机器小伟]一起继续学习统计方面的绘图知识。


    今天[人叫板老师]提出了条形统计图的概念,小伟决定要好好地画一画。



    小伟说:我能,就画了这张图:




    这次,小伟在左边也加上了说明的数字。



    这次,小伟又加上了坐标轴。







    小伟又试着用另一种方向来绘制:









    小伟的图已经画得和[人叫板老师]的一样了。

    而这时,也已经产生了一个完整的工具:

    <span style="font-size:18px;">/**
    * @usage   统计类
    * @author  mw
    * @date    2016年01月05日  星期二  10:14:34 
    * @param
    * @return
    *
    */
    function Statistic() {
    	this.statisticalSample = new Array();
    	this.sampleSize = 0;
    	this.xLabel = '';
    	this.yLabel = '';
    
    	//初始化
    	this.init = function(array, textX, textY) {
    		this.statisticalSample = array;
    		this.sampleSize = this.statisticalSample.length;
    		this.xLabel = textX;
    		this.yLabel = textY;
    	}
    	
    	this.axis2D = function(x, y, rx, ry, textX, textY) {
    		//原点是(x, y), rx, ry分别是x轴的长度,y轴的长度
    		//textX, textY分别为x轴和y轴的标注
    		plot.save();
    		
    		plot.setFillStyle('black')
    			.setStrokeStyle('black');
    			
    		plot.beginPath()
    			.moveTo(x,y)
    			.lineTo(x+rx,y)
    			.closePath()
    			.stroke();
    			
    		plot.beginPath()
    			.moveTo(x,y-ry)
    			.lineTo(x,y)
    			.closePath()
    			.stroke();		
    
    		
    		var r0 = 10;
    		
    		//x轴箭头
    		plot.beginPath()
    			.moveTo(x+rx- r0*Math.cos(Math.PI/3), y-r0*Math.sin(Math.PI/3))
    			.lineTo(x+rx+r0*Math.sin(Math.PI/3), y)
    			.lineTo(x+rx -r0*Math.cos(Math.PI/3), y+r0*Math.sin(Math.PI/3))
    			.closePath()
    			.fill()
    		
    		plot.setTextAlign('left')
    			.fillText(textX, x+rx, y+25, 40);
    		plot.setTextAlign('right')
    			.fillText(textY, x-10, y-ry+10, 40);
    		
    		//y轴箭头
    		plot.beginPath()
    			.moveTo(x+ r0*Math.sin(Math.PI/3), y-ry+r0*Math.cos(Math.PI/3))
    			.lineTo(x, y-ry-r0*Math.sin(Math.PI/3))
    			.lineTo(x-r0*Math.sin(Math.PI/3), y-ry+r0*Math.cos(Math.PI/3))
    			.closePath()
    			.fill()
    		
    		plot.restore();
    	}	
    	
    	//最大值
    	this.max = function() {
    		var max = Number.NEGATIVE_INFINITY;
    		for (var i = 0; i < this.sampleSize; i++) {
    	
    			if (max < this.statisticalSample[i]) {
    				max = this.statisticalSample[i];
    			}
    		}
    		return max;
    	}
    	
    	//最小值
    	this.min = function() {
    		var min = Number.POSITIVE_INFINITY;
    		for (var i = 0; i < this.sampleSize; i++) {
    			if (min > this.statisticalSample[i]) {
    				min = this.statisticalSample[i];
    			}
    		}
    		return min;
    	}
    	
    	//样本数量
    	this.size = function() {
    		return this.sampleSize;
    	}
    	
    	//直方图
    	this.histogram = function(lableArray, xOffset, yOffset) {
    		lableArray = lableArray ? lableArray : [];
    		var lables = lableArray.length;
    		xOffset = xOffset ? xOffset : 0;
    		yOffset = yOffset ? yOffset : 0;
    		
    		var colorArray = ['red', 'orange', '#0088FF', 'green', 'cyan', 'blue', '#FF00FF',
    			'#888888', 'black'];
    		var colors = colorArray.length;
    			
    		var height = 380, width = 580;
    		
    		plot.save()
    			.translate(xOffset+60, yOffset+50);
    
    		plot.setLineWidth(2)
    			.setTextAlign('right');
    			
    		var max = Math.ceil(this.max());  
    		var min = Math.floor(this.min()); 
    		
    		var mod = 10;
    		while (max % mod == 0) {
    			mod *= 10;
    		}
    		
    		mod /= 10;
    		//最大值的末位为0的近似数,比如最大值25,最合适的近似数为30
    		var adjmax = Math.ceil(max/mod)*mod;
    		if (adjmax == max) {
    			adjmax+=mod;
    		}
    		
    		adjmax /= mod;
    		
    		var size = this.size();  
    		var perH = Math.round((height-100) / adjmax);  
    		var perW = Math.round((width-100) / (size*2+1));
    		
    		//宽和高度边界
    		var wBound = (2*size+1)*perW, hBound = adjmax*perH;
    		plot.setLineWidth(5)
    			.strokeRect(0, 0, wBound, hBound);
    			
    		this.axis2D(0, hBound, wBound+20, hBound+20, this.xLabel, this.yLabel);
    			
    		plot.setLineWidth(2);
    		var count = 0;
    		for (var i = hBound; i >-1; i -= hBound / 10) {
    			plot.fillText((adjmax*mod/10*count).toFixed(0), -10, i+10, 30);
    			count++;
    			
    			if (i > 0) {
    				plot.beginPath()
    					.moveTo(0, i)
    					.lineTo(wBound, i)
    					.closePath()
    					.stroke();
    			}
    		}
    		
    		for (var i = 0; i < 2*size+1; i++) {
    			plot.beginPath()
    				.moveTo(i*perW, 0)
    				.lineTo(i*perW, hBound)
    				.closePath()
    				.stroke();
    		}
    		
    
    		
    		var xpos, xpos2;
    		
    		for (var i = 0; i < size; i++) { 
    			xpos = perW*(1+2*i);
    			xpos2 = xpos + 0.5*perW;
    			plot.setFillStyle(colorArray[i%colors]);  
    			plot.fillRect(perW*(1+2*i), hBound, perW, -this.statisticalSample[i]/mod*perH); 
    			
    			plot.setTextAlign('center');
    			if (i < lables) {
    				plot.fillText(lableArray[i], xpos2, 
    					hBound+30, 100);  
    
    			}
    			//plot.fillText(this.statisticalSample[i].toFixed(0), xpos2, hBound+40, 100);  
    		}  
    
    		
    		plot.restore();
    	
    	}
    		
    	//垂直方向直方图
    	this.verticalhistogram = function(lableArray, xOffset, yOffset) {
    		lableArray = lableArray ? lableArray : [];
    		var lables = lableArray.length;
    		xOffset = xOffset ? xOffset : 0;
    		yOffset = yOffset ? yOffset : 0;
    		
    		var colorArray = ['red', 'orange', '#0088FF', 'green', 'cyan', 'blue', '#FF00FF',
    			'#888888', 'black'];
    		var colors = colorArray.length;
    			
    		var height = 380, width = 580;
    		
    		plot.save()
    			.translate(xOffset+60, yOffset+50);
    			
    		var max = Math.ceil(this.max());  
    		var min = Math.floor(this.min()); 
    		
    		var mod = 10;
    		while (max % mod == 0) {
    			mod *= 10;
    		}
    		//最大值的末位为0的近似数,比如最大值25,最合适的近似数为30
    		mod /= 10;
    		var adjmax = Math.ceil(max/mod)*mod;
    		if (adjmax == max) {
    			adjmax+=mod;
    		}
    		
    		adjmax /= mod;
    		
    		
    		var size = this.size();  
    		var perH = Math.round((height-100) / (size*2+1));			  
    		var perW = Math.round((width-100) / adjmax);
    		
    		//宽和高度边界
    		var hBound = (2*size+1)*perH, wBound = adjmax*perW;
    		plot.setLineWidth(5)
    			.strokeRect(0, 0, wBound, hBound);
    			
    		this.axis2D(0, hBound, wBound+20, hBound+20, this.xLabel, this.yLabel);
    			
    		plot.setLineWidth(2)
    			.setTextAlign('center');
    		var count = 0;
    		for (var i = 0; i < wBound+1; i += wBound / 10) {
    			plot.fillText((adjmax*mod/10*count).toFixed(0), i, hBound+25, 30);
    			count++;
    			
    			if (i > 0) {
    				plot.beginPath()
    					.moveTo(i, 0)
    					.lineTo(i, hBound)
    					.closePath()
    					.stroke();
    			}
    		}
    		
    		for (var i = 0; i < 2*size+1; i++) {
    			plot.beginPath()
    				.moveTo(0, i*perH)
    				.lineTo(wBound, i*perH)
    				.closePath()
    				.stroke();
    		}
    		
    
    		
    		var ypos, ypos2;
    		
    		for (var i = 0; i < size; i++) { 
    			ypos = perH*(1+2*i);
    			ypos2 = ypos + 0.5*perH+5;
    			plot.setFillStyle(colorArray[i%colors]);  
    			plot.fillRect(0, ypos, this.statisticalSample[i]/mod*perW, perH); 
    			
    			plot.setTextAlign('right');
    			if (i < lables) {
    				plot.fillText(lableArray[i], -10, ypos2, 100);  
    
    			}
    			
    		}  
    
    		
    		plot.restore();
    	
    	}
    }</span>

    而小伟画上面的那些图是这样做的:

    <span style="font-size:18px;">function myDraw() {  
        var config = new PlotConfiguration();  
        config.init();  
        config.setPreference(); 
    	//config.setSector(1,1,1,1);
     
        //config.axis2D(0, 0, 180);  	
    	
    	var stat = new Statistic();
    	
    	var data = [9,6,9,7];
    	var text = ['晴', '阴', '多云', '雨'];
    	var textX = '天气',textY = '天数';
    	
    	stat.init(data, textX, textY);
    	stat.histogram(text, 20, 50);
    
    			
    }
    
    
    function myDraw() {  
        var config = new PlotConfiguration();  
        config.init();  
        config.setPreference(); 
    	//config.setSector(1,1,1,1);
     
        //config.axis2D(0, 0, 180);  	
    	
    	var stat = new Statistic();
    	
    	var data = [18,4,5,3];
    	var text = ['晴', '阴', '多云', '雨'];
    	var textX = '天气',textY = '天数';
    	
    	stat.init(data, textX, textY);
    	stat.histogram(text, 20, 50);
    
    			
    }
    
    function myDraw() {  
        var config = new PlotConfiguration();  
        config.init();  
        config.setPreference(); 
    	//config.setSector(1,1,1,1);
     
        //config.axis2D(0, 0, 180);  	
    	
    	var stat = new Statistic();
    	
    	var data = [50, 30, 25,10];
    	var text = ['轿车', '面包车', '客车', '货车'];
    	var textX = '机动车',textY = '辆数';
    	
    	stat.init(data, textX, textY);
    	stat.histogram(text, 20, 50);
    
    			
    }
    
    function myDraw() {  
        var config = new PlotConfiguration();  
        config.init();  
        config.setPreference(); 
    	//config.setSector(1,1,1,1);
     
        //config.axis2D(0, 0, 180);  	
    	
    	var stat = new Statistic();
    	
    	var data = [15,10,20,25,30,50,45];
    	var text = ['一', '二', '三', '四', '五', '六', '日'];
    	var textX = '星期',textY = '销售量/台';
    	
    	stat.init(data, textX, textY);
    	stat.histogram(text, 0, 0);
    
    			
    }
    
    function myDraw() {  
        var config = new PlotConfiguration();  
        config.init();  
        config.setPreference(); 
    	//config.setSector(1,1,1,1);
     
        //config.axis2D(0, 0, 180);  	
    	
    	var stat = new Statistic();
    	
    	var data = [15,10,20,25,30,50,45];
    	var text = ['一', '二', '三', '四', '五', '六', '日'];
    	var textX = '星期',textY = '销售量/台';
    	
    	stat.init(data, textX, textY);
    	stat.verticalhistogram(text, 0, 0);
    
    			
    }
    
    function myDraw() {  
        var config = new PlotConfiguration();  
        config.init();  
        config.setPreference(); 
    	//config.setSector(1,1,1,1);
     
        //config.axis2D(0, 0, 180);  	
    	
    	var stat = new Statistic();
    	
    	var data = [40,75,25,10];
    	var text = ['河马', '大象', '长颈鹿', '狗'];
    	var textX = '平均寿命/年',textY = '动物';
    	
    	stat.init(data, textX, textY);
    	stat.verticalhistogram(text, 0, 0);
    
    			
    }
    
    
    function myDraw() {  
        var config = new PlotConfiguration();  
        config.init();  
        config.setPreference(); 
    	//config.setSector(1,1,1,1);
     
        //config.axis2D(0, 0, 180);  	
    	
    	var stat = new Statistic();
    	
    	var data = [300,800,1200,1000,500,700,200];
    	var text = ['汽车', '运动', '时尚', '娱乐', '经济', '饮食', '其他'];
    	var textX = '本数',textY = '种类';
    	
    	stat.init(data, textX, textY);
    	stat.verticalhistogram(text, 10, 10);
    
    			
    }
    
    
    function myDraw() {  
        var config = new PlotConfiguration();  
        config.init();  
        config.setPreference(); 
    	//config.setSector(1,1,1,1);
     
        //config.axis2D(0, 0, 180);  	
    	
    	var stat = new Statistic();
    	
    	var data = [300,800,1200,1000,500,700,200];
    	var text = ['汽车', '运动', '时尚', '娱乐', '经济', '饮食', '其他'];
    	var textX = '种类',textY = '本数';
    	
    	stat.init(data, textX, textY);
    	stat.histogram(text, 0, 0);
    
    			
    }</span>

    当然,越后面的正确性越高,因为工具是在不断改进的。

    本节到此结束,欲知后事如何,请看下回分解。



    展开全文
  • Java对图形文件解析(包括普通图片文件、验证码、统计图条形码和二维码) 其中,关于统计图条形码和二维码,jdk本身并没有相关操作工具包,大多通过在Maven repository中添加第三方库来实现生成与解析 1、...

    Java对图形文件的解析(包括普通图片文件、验证码、统计图、条形码和二维码)

    其中,关于统计图、条形码和二维码,jdk本身并没有相关操作的工具包,大多通过在Maven repository中添加第三方库来实现生成与解析

    1、图形图像及解析

    图形图像基础概念
    • 图形:Graph
      • 矢量图,根据几何特性来画的,比如点、直线、弧线等
    • 图像:Image
      • 由像素点组成
      • 格式:jpg,png,bmp,gif,svg,wmf,tiff等
    Java图形图像关键类
    • 图形:Graph
      • java.awt包(Java中处理图形的主要类库)
      • Java 2D库:Graphics2D,Line2D,Rectangle2D,Ellipse2D,Arc2D(弧形)
      • Color,Stroke(线条)
    • 图像
      • java.imageio包
      • ImageIO,BufferedImage,ImageReader,ImageWriter

    java图像关键类描述

    • Java原生支持jpg,png,bmg,gif,wbmp
    • javax.imageio.ImageIO
      • 自动封装多种ImageReader和ImageWriter,读写图像文件
      • read读取图片,write写图片
    • java.awt.image.BufferedImage,图像在内存中的表示类
      • getHeight 获取高度
      • getWidth 获取宽度

    eg:

    readAndWriteImage:

    public static void readAndWrite() throws Exception {
        BufferedImage image = ImageIO.read(new File("c:\1.jpg"));//图片位置
        System.out.println("Height: " + image.getHeight()); // 高度像素
        System.out.println("Width: " + image.getWidth()); // 宽度像素
        ImageIO.write(image, "png", new File("c:/2.png"));//重新写入图片位置
    }
    

    在已知图像格式,选定了该格式的reader,加载速度更快

    // 指定用jpg Reader来加载,速度会加快
    Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("jpg");
    ImageReader reader = (ImageReader) readers.next();
    System.out.println(reader.getClass().getName());
    ImageInputStream iis = ImageIO.createImageInputStream(new File("c:/1.jpg"));
    reader.setInput(iis, true);
    System.out.println("Height:" + reader.getHeight(0));
    System.out.println("Width:" + reader.getWidth(0));
    

    裁剪图片

    /**
     * cropImage 将原始图片文件切割一个矩形,并输出到目标图片文件
     * @param fromPath 原始图片
     * @param toPath  目标图片
     * @param x       坐标起点x
     * @param y       坐标起点y
     * @param width   矩形宽度
     * @param height  矩形高度
     * @param readImageFormat  原始文件格式
     * @param writeImageFormat 目标文件格式
     * @throws Exception
     */
    public static void cropImage(String fromPath, String toPath, int x, int y, int width, int height, String readImageFormat,
            String writeImageFormat) throws Exception {
        FileInputStream fis = null;
        ImageInputStream iis = null;
        try {
            // 读取原始图片文件
            fis = new FileInputStream(fromPath);
            Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName(readImageFormat);
            ImageReader reader = it.next();			
            iis = ImageIO.createImageInputStream(fis);
            reader.setInput(iis, true);
    
            // 定义一个矩形 并放入切割参数中
            ImageReadParam param = reader.getDefaultReadParam();			
            Rectangle rect = new Rectangle(x, y, width, height);			
            param.setSourceRegion(rect);
    
            //从源文件读取一个矩形大小的图像
            BufferedImage bi = reader.read(0, param);
    
            //写入到目标文件
            ImageIO.write(bi, writeImageFormat, new File(toPath));
        } finally {
            fis.close();
            iis.close();
        }
    }
    

    拼接图片

    /**
     * 横向拼接两张图片,并写入到目标文件
     * 拼接的本质,就是申请一个大的新空间,然后将原始的图片像素点拷贝到新空间,最后保存
     * @param firstPath 第一张图片的路径
     * @param secondPath    第二张图片的路径
     * @param imageFormat   拼接生成图片的格式
     * @param toPath    目标图片的路径
     */
    public static void combineImagesHorizontally(String firstPath, String secondPath,String imageFormat, String toPath){  
        try {  
            //读取第一张图片    
            File  first  =  new  File(firstPath);    
            BufferedImage  imageOne = ImageIO.read(first);    
            int  width1  =  imageOne.getWidth();//图片宽度    
            int  height1  =  imageOne.getHeight();//图片高度    
            //从第一张图片中读取RGB    
            int[]  firstRGB  =  new  int[width1*height1];    
            firstRGB  =  imageOne.getRGB(0,0,width1,height1,firstRGB,0,width1);    
    
            //对第二张图片做同样的处理    
            File  second  =  new  File(secondPath);    
            BufferedImage  imageTwo  =  ImageIO.read(second); 
            int width2 = imageTwo.getWidth();
            int height2 = imageTwo.getHeight();
            int[]   secondRGB  =  new  int[width2*height2];    
            secondRGB  =  imageTwo.getRGB(0,0,width2,height2,secondRGB,0,width2);   
    
            //生成新图片
            int height3 = (height1>height2)?height1:height2; //挑选高度大的,作为目标文件的高度
            int width3  = width1 + width2;                   //宽度,两张图片相加
            BufferedImage  imageNew  =  new  BufferedImage(width3,height3,BufferedImage.TYPE_INT_RGB);    
    
            //设置左半部分的RGB 从(0,0) 开始 
            imageNew.setRGB(0,0,width1,height1,firstRGB,0,width1); 
            //设置右半部分的RGB 从(width1, 0) 开始 
            imageNew.setRGB(width1,0,width2,height2,secondRGB,0,width2);
    
            //保存图片
            ImageIO.write(imageNew,  imageFormat,  new  File(toPath));
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }
    
    /**
     * 纵向拼接图片(两张)
     * 拼接的本质,就是申请一个大的新空间,然后将原始的图片像素点拷贝到新空间,最后保存
     * @param firstPath 读取的第一张图片
     * @param secondPath    读取的第二张图片
     * @param imageFormat 图片写入格式
     * @param toPath    图片写入路径
     */
    public static void combineImagesVertically(String firstPath, String secondPath,String imageFormat, String toPath){  
        try {  
            //读取第一张图片    
            File  first  =  new  File(firstPath);    
            BufferedImage  imageOne = ImageIO.read(first);    
            int  width1  =  imageOne.getWidth();//图片宽度    
            int  height1  =  imageOne.getHeight();//图片高度    
            //从图片中读取RGB    
            int[]  firstRGB  =  new  int[width1*height1];    
            firstRGB  =  imageOne.getRGB(0,0,width1,height1,firstRGB,0,width1);    
    
            //对第二张图片做相同的处理    
            File  second  =  new  File(secondPath);    
            BufferedImage  imageTwo  =  ImageIO.read(second); 
            int width2 = imageTwo.getWidth();
            int height2 = imageTwo.getHeight();
            int[]   secondRGB  =  new  int[width2*height2];    
            secondRGB  =  imageTwo.getRGB(0,0,width2,height2,secondRGB,0,width2); 
    
            //生成新图片
            int width3 = (width1>width2)?width1:width2; //挑选宽度大的,作为目标文件的宽度
            int height3 = height1+height2;              //高度,两张图片相加
            BufferedImage  imageNew  =  new  BufferedImage(width3,height3,BufferedImage.TYPE_INT_RGB);    
            //设置上半部分的RGB 从(0,0) 开始 
            imageNew.setRGB(0,0,width1,height1,firstRGB,0,width1);
            //设置下半部分的RGB 从(0, height1) 开始 
            imageNew.setRGB(0,height1,width2,height2,secondRGB,0,width2);  
            //保存图片
            ImageIO.write(imageNew, imageFormat, new File(toPath));
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }
    

    2、验证码的生成及解析

    验证码 ,一个图片文件

    设计验证码需要考虑:

    • 外框、底色、干扰线、字母等

    产生验证码的java程序

    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics2D;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.util.Random;
    import javax.imageio.ImageIO;
    
    public class ValidateCodeTest {
    
    	//没有1 I L 0 o
    	static char[] codeSequence = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q', 'R', 'S', 'T',
    			'U', 'V', 'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9' };
    	static int charNum = codeSequence.length;
    	
    	public static void main(String[] a) throws IOException
    	{
    		generateCode("c:/1.jpg");
    	}	
    	
    
    	public static void generateCode(String filePath) throws IOException {
    		// 首先定义验证码图片框  
    		int width = 80; // 验证码图片的宽度
    		int height = 32; // 验证码图片的高度
            BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 
            
            
            //定义图片上的图形和干扰线
            Graphics2D gd = buffImg.createGraphics();   
            gd.setColor(Color.LIGHT_GRAY);   // 将图像填充为浅灰色   
            gd.fillRect(0, 0, width, height);   
            gd.setColor(Color.BLACK);        // 画边框。   
            gd.drawRect(0, 0, width - 1, height - 1);   
            // 随机产生16条灰色干扰线,使图像中的认证码不易识别  
            gd.setColor(Color.gray); 
            // 创建一个随机数生成器类   用于随机产生干扰线
            Random random = new Random();   
            for (int i = 0; i < 16; i++) {   
                int x = random.nextInt(width);   
                int y = random.nextInt(height);   
                int xl = random.nextInt(12);   
                int yl = random.nextInt(12);   
                gd.drawLine(x, y, x + xl, y + yl);   
            }   
            
            
            //计算字的位置坐标
            int codeCount = 4; // 字符个数
        	int fontHeight; // 字体高度
        	int codeX; // 第一个字符的x坐标,因为后面的字符坐标依次递增,所以它们的x轴值是codeX的倍数
        	int codeY; // 验证字符的y坐标,因为并排所以值一样
        	// width-4 除去左右多余的位置,使验证码更加集中显示,减得越多越集中。
        	// codeCount+1 //等比分配显示的宽度,包括左右两边的空格
        	codeX = (width - 4) / (codeCount + 1); //第一个字母的起始位置    	
        	fontHeight = height - 10;  // height - 10 高度中间区域显示验证码
        	codeY = height - 7;
        			
        			
            // 创建字体,字体的大小应该根据图片的高度来定。   
            Font font = new Font("Fixedsys", Font.PLAIN, fontHeight);           
            gd.setFont(font);   
            
            // 随机产生codeCount数字的验证码。   
            for (int i = 0; i < codeCount; i++) {   
                // 每次随机拿一个字母,赋予随机的颜色  
                String strRand = String.valueOf(codeSequence[random.nextInt(charNum)]);   
                int red = random.nextInt(255);   
                int green = random.nextInt(255);   
                int blue = random.nextInt(255);   
                gd.setColor(new Color(red,green,blue));   
                //把字放到图片上!!!
                gd.drawString(strRand, (i + 1) * codeX, codeY);              
            }   
            
            ImageIO.write(buffImg, "jpg", new File(filePath));             
    	}
    }
    
    

    3、统计图的生成

    统计图包括柱状图、饼图、折线图

    • Java原生Graphics 2D可以画,比较繁琐
    • 这里采用第三方库,jFreeChart可以快速实现统计图的绘制
      • 设定数据集
      • 调用CharFactory生成图形

    pom.xml中添加依赖:

    <dependency>
        <groupId>org.jfree</groupId>
        <artifactId>jfreechart</artifactId>
        <version>1.0.19</version>
    </dependency>
    

    创建统计图的实例:

    import java.awt.Font;
    import java.io.File;
    import java.io.IOException;
    
    import org.jfree.chart.ChartFactory;
    import org.jfree.chart.ChartUtilities;
    import org.jfree.chart.JFreeChart;
    import org.jfree.chart.StandardChartTheme;
    import org.jfree.chart.plot.PlotOrientation;
    import org.jfree.data.category.DefaultCategoryDataset;
    import org.jfree.data.general.DefaultPieDataset;
    
    public class JFreeChartTest {
    
    	public static void main(String[] args) {
    		writeBar("c:/bar.jpg"); // 柱状图
    		writePie("c:/pie.jpg"); // 饼图
    		writeLine("c:/line.jpg");// 折线图
    	}
    	
    	public static StandardChartTheme getChineseTheme()
    	{
    		StandardChartTheme chineseTheme = new StandardChartTheme("CN");
    		chineseTheme.setExtraLargeFont(new Font("隶书", Font.BOLD, 20));
    		chineseTheme.setRegularFont(new Font("宋书", Font.PLAIN, 15));
    		chineseTheme.setLargeFont(new Font("宋书", Font.PLAIN, 15));
    		return chineseTheme;
    	}
    	
    	public static void writeBar(String fileName) {
    		DefaultCategoryDataset dataset = new DefaultCategoryDataset();
    		dataset.addValue(11, "", "第一季度");
    		dataset.addValue(41, "", "第二季度");
    		dataset.addValue(51, "", "第三季度");
    		dataset.addValue(4, "", "第四季度");
    
    		// PlotOrientation.HORIZONTAL横向 PlotOrientation.VERTICAL 竖向
    		// 引入中文主题样式
    		ChartFactory.setChartTheme(getChineseTheme());
    		JFreeChart chart = ChartFactory.createBarChart3D("柱状图", "2018年", "产品总量", dataset, PlotOrientation.VERTICAL,
    				false, false, false);
    
    		try {
    			ChartUtilities.saveChartAsJPEG(new File(fileName), chart, 600, 300);
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    
    	}
    
    	public static void writePie(String fileName) {
    		DefaultPieDataset pds = new DefaultPieDataset();
    		pds.setValue("C人数", 100);
    		pds.setValue("C++人数", 200);
    		pds.setValue("Java人数", 300);
    		try {
    			ChartFactory.setChartTheme(getChineseTheme());
    			JFreeChart chart = ChartFactory.createPieChart("饼图", pds);
    			
    			ChartUtilities.saveChartAsJPEG(new File(fileName), chart, 600, 300);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    	public static void writeLine(String fileName) {
    		DefaultCategoryDataset lines = new DefaultCategoryDataset();
    		//第一条线
    		lines.addValue(100, "Java核心技术", "1月");
    		lines.addValue(200, "Java核心技术", "2月");
    		lines.addValue(400, "Java核心技术", "3月");
    		lines.addValue(500, "Java核心技术", "4月");
    		
    		//第二条线
    		lines.addValue(100, "Java核心技术(进阶)", "1月");
    		lines.addValue(400, "Java核心技术(进阶)", "2月");
    		lines.addValue(900, "Java核心技术(进阶)", "3月");
    		try {
    			ChartFactory.setChartTheme(getChineseTheme());
    			JFreeChart chart = ChartFactory.createLineChart("折线图", "时间", "人数", lines);
    			ChartUtilities.saveChartAsJPEG(new File(fileName), chart, 600, 300);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    

    4、条形码和二维码

    条形码
    • 将宽度不等的多个黑 条 和 空 白 , 按照一定的编码规则排列 , 用以表达一组信息的图形标识符
    • 通常代表一串数字/ 字母 ,每一位有特殊的含义
    • 一般数据容量30个数字/字母
    二维码
    • 用某种特定的几何图形按一定规律在平面 ( 二维方向上 ) 分布的黑白相间的图形记录数据符号信息
    • 比一维条形码能存更多信息 ,表示更多数据类型
    • 能够存储数字/ / 字母/ / 汉字/ / 图片等信息
    • 可存储几百到几十KB字符
    • 抗损坏

    这里采用第三方库ZXing(Zebra Crossing)实现生成和解析条形码、二维码

    pom.xml添加依赖

    <!-- https://mvnrepository.com/artifact/com.google.zxing/core -->
    	<dependency>
    	    <groupId>com.google.zxing</groupId>
    	    <artifactId>core</artifactId>
    	    <version>3.3.3</version>
    	</dependency>
      	<!-- https://mvnrepository.com/artifact/com.google.zxing/javase -->
    	<dependency>
    	    <groupId>com.google.zxing</groupId>
    	    <artifactId>javase</artifactId>
    	    <version>3.3.3</version>
    	</dependency>
    
    • ZXing(Zebra Crossing),Google出品,支持1D和2D的Barcode
    • 主要类:
      • BitMatrix位图矩阵
      • MultiFormatWriter位图编辑器
      • MatrixToImageWriter写入图片
    条形码生成和解析
    import com.google.zxing.BarcodeFormat;
    import com.google.zxing.BinaryBitmap;
    import com.google.zxing.DecodeHintType;
    import com.google.zxing.EncodeHintType;
    import com.google.zxing.LuminanceSource;
    import com.google.zxing.MultiFormatReader;
    import com.google.zxing.MultiFormatWriter;
    import com.google.zxing.Result;
    import com.google.zxing.WriterException;
    import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
    import com.google.zxing.client.j2se.MatrixToImageWriter;
    import com.google.zxing.common.BitMatrix;
    import com.google.zxing.common.HybridBinarizer;
    
    import javax.imageio.ImageIO;
    
    import java.awt.image.BufferedImage;
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.util.HashMap;
    import java.util.Map;
    
    public class BarCodeTest {
    	/**
    	 * generateCode 根据code生成相应的一维码
    	 * @param file 一维码目标文件
    	 * @param code 一维码内容
    	 * @param width 图片宽度
    	 * @param height 图片高度
    	 */
        public static void generateCode(File file, String code, int width, int height) {
        	//定义位图矩阵BitMatrix
            BitMatrix matrix = null;
            try {
                // 使用code_128格式进行编码生成100*25的条形码
            	MultiFormatWriter writer = new MultiFormatWriter();
            	
                matrix = writer.encode(code,BarcodeFormat.CODE_128, width, height, null);
                //matrix = writer.encode(code,BarcodeFormat.EAN_13, width, height, null);
            } catch (WriterException e) {
                e.printStackTrace();
            }
            
            //将位图矩阵BitMatrix保存为图片
            try (FileOutputStream outStream = new FileOutputStream(file)) {
                ImageIO.write(MatrixToImageWriter.toBufferedImage(matrix), "png",
                        outStream);
                outStream.flush();
            } catch (Exception e) {
            	e.printStackTrace();
            }
        }
        
        /**
         * readCode 读取一张一维码图片
         * @param file 一维码图片名字
         */
        public static void readCode(File file){
            try {
            	BufferedImage image = ImageIO.read(file);
                if (image == null) {
                    return;
                }
                LuminanceSource source = new BufferedImageLuminanceSource(image);
                BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
                
                Map<DecodeHintType, Object> hints = new HashMap<>();
                hints.put(DecodeHintType.CHARACTER_SET, "GBK");
                hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
                hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
                
                Result result = new MultiFormatReader().decode(bitmap, hints);
                System.out.println("条形码内容: "+result.getText());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) throws Exception {
            generateCode(new File("f:\\1dcode.png"), "123456789012", 500, 250);
        	readCode(new File("1dcode.png"));
        }
    }
    
    
    二维码生成和解析(主要是QRCode)
    import com.google.zxing.*;
    import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
    import com.google.zxing.client.j2se.MatrixToImageWriter;
    import com.google.zxing.common.BitMatrix;
    import com.google.zxing.common.HybridBinarizer;
    import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
    
    import javax.imageio.ImageIO;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.nio.file.Path;
    import java.util.HashMap;
    import java.util.Map;
    
    public class QRCodeTest {
        /*
         * 定义二维码的宽高
         */
        private static int WIDTH = 300;
        private static int HEIGHT = 300;
        private static String FORMAT = "png";//二维码格式
    
        //生成二维码
        public static void generateQRCode(File file, String content) {
            //定义二维码参数
            Map<EncodeHintType, Object> hints = new HashMap<>();
    
            hints.put(EncodeHintType.CHARACTER_SET, "utf-8");//设置编码
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);//设置容错等级
            hints.put(EncodeHintType.MARGIN, 2);//设置边距默认是5
    
            try {
                BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, WIDTH, HEIGHT, hints);
                Path path = file.toPath();
                MatrixToImageWriter.writeToPath(bitMatrix, FORMAT, path);//写到指定路径下
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
        //读取二维码
        public static void readQrCode(File file) {
            MultiFormatReader reader = new MultiFormatReader();
            try {
                BufferedImage image = ImageIO.read(file);
                BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(image)));
                Map<DecodeHintType, Object> hints = new HashMap<>();
                hints.put(DecodeHintType.CHARACTER_SET, "utf-8");//设置编码
                Result result = reader.decode(binaryBitmap, hints);
                System.out.println("解析结果:" + result.toString());
                System.out.println("二维码格式:" + result.getBarcodeFormat());
                System.out.println("二维码文本内容:" + result.getText());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        public static void main(String[] args) {
            generateQRCode(new File("2dcode.png"), "https://www.baidu.com");
           //readQrCode(new File("2dcode.png"));
           //readQrCode(new File("2dcode.jpg"));
        }
    }
    
    展开全文
  • matplotlib条形图

    2020-03-11 16:23:15
    一、概念 (一)以长方形长度为变量的统计图表 (二)用来比较多个项目分类数据大小 ...1、垂直条形图 import numpy as np import matplotlib.pyplot as plt import matplotlib.dates as mdates N=5 y=[20,10,3...

    一、概念
    (一)以长方形的长度为变量的统计图表
    (二)用来比较多个项目分类的数据大小
    (三)通常利用于较小的数据集分析
    (四)例如不同季度的销量、不同国家的人口等
    二、实践
    (一)举例
    1、垂直条形图
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.dates as mdates
    N=5
    y=[20,10,30,25,15]
    index=np.arange(N)
    plt.bar(index,height=y,color=‘gray’,width=0.5)
    plt.show()
    在这里插入图片描述
    2、水平条形图
    (1)由垂直的变为水平的
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.dates as mdates
    N=5
    y=[20,10,30,25,15]
    index=np.arange(N)
    plt.bar(0,bottom=index,width=y,color=‘gray’,height=0.5,orientation=‘horizontal’)
    plt.show()
    在这里插入图片描述
    (2)直接创建水平的
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.dates as mdates
    N=5
    y=[20,10,30,25,15]
    index=np.arange(N)
    plt.barh(index,y,height=0.5,color=‘gray’)
    plt.show()
    在这里插入图片描述
    3、层叠式/并列式形图
    (1)并列式
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.dates as mdates
    index=np.arange(4)
    sales_BJ=[52,55,63,53]
    sales_SH=[44,66,55,41]
    bar_width=0.3
    plt.bar(index,sales_BJ,bar_width,color=‘b’)
    plt.bar(index+bar_width,sales_SH,bar_width,color=‘r’)
    plt.show()
    在这里插入图片描述
    (2)层叠式
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.dates as mdates
    index=np.arange(4)
    sales_BJ=[52,55,63,53]
    sales_SH=[44,66,55,41]
    bar_width=0.3
    plt.bar(index,sales_BJ,bar_width,color=‘b’)
    plt.bar(index,sales_SH,bar_width,color=‘r’,bottom=sales_BJ)
    plt.show()
    在这里插入图片描述
    (二)参数
    1、颜色,color
    2、宽度,width

    展开全文
  • matplotlib-条形图

    2017-09-17 11:05:12
    以长方形长度为变量的统计图像 用来比较多个项目分类数据 通常利用与较小数据集分析 例如不同季度销量,不同国家人口等 import numpy as np import matplotlib.pyplot as plt N = 5 y = [10,20...

    概念

    以长方形的长度为变量的统计图像

    用来比较多个项目分类的数据

    通常利用与较小的数据集分析

    例如不同季度的销量,不同国家的人口等

    import numpy as np

    import matplotlib.pyplot as plt


    N = 5

    y = [10,20,30,40,78]

    index  = np.arrage(N)

    p1=plt.bar(left=index,height=y,color='blue',width=0.5)

    #水平条形图 orientation="horizontal",bottom=index,left=0

    #plt.barh()函数简化

    plt.show()

    作业:

    生成两组大小为5的数据(数据自选)

    画出两组数据水平的条形图

    采用并列和层叠两种方式



    展开全文
  • 诸如条形图之类基本可视化可能会为您提供一些高级信息,但通过统计,我们可以以更加信息驱动和有针对性方式对数据进行操作。所涉及数学帮助我们形成关于我们数据具体结论,而不仅仅是猜测。 使用统计数据.....
  • 剧情提要: [机器小伟]在[工程师阿伟]的陪同下进入练气期第十层功法的修炼, 这次要修炼的目标是[折线统计图]。 ...[人叫板老师]是根据条形图引出了折线图的概念,小伟决定也这样做。 上次绘
  • 统计

    2017-06-03 23:12:39
    网易公开课 可汗学院 统计学0.基本概念 均值 mean 样本值和/样本个数 中位数 middle:从小到大排列后最中间1个数,如果偶数个样本...象形统计图 pictograph 条形图 bar graph 适用于将事物归类,看每一类分别是什么
  • 2.6 数据展示——统计图 . 35 2.6.1 条形图与扇形图. 36 2.6.2 折线图 36 2.6.3 茎叶图 37 2.6.4 箱线图 40 2.6.5 统计图小结 42 2.7 使用 Excel 实现数据描述性统计及分析 43 2.7.1 使用 Excel 实现三国全部...
  • 一个基本可视化,如条形图,可以给你提供一些高级信息,但是通过统计学,我们可以以一种更加以信息驱动和更有针对性方式来操作数据。所用到数学方法能帮助我们对数据形成具体结论,而不是去靠猜测。 通过...
  • 直方:直方是一种统计报告,形式上也是一个个长条形,但是直方用长条形面积表示频数,所以长条形高度表示频数/组距,宽度表示组距,其长度和宽度均有意义。当宽度相同时,一般就用长条形长度表示频数...
  • 该函数在概念上类似于MATLABrose和polarhistogram函数,但在以下几个方面有所不同: 与其将直方箱绘制为楔形,不如将它们绘制为直条形。 直方箱可以具有误差线。 半径轴比例在旁边显示为直线比例。 ...
  • 条形码、标准答题卡相比较,惯性导航信息标记点的图像有许多不可预测的污染,比如曝光质量差、灰尘、指纹...通过把投影转换成一维信号的概念,提供了一致的分析方法,提高了处理效率;通过引入聚类思想计算标记点高度
  • 统计学期末总复习

    千次阅读 多人点赞 2020-06-23 23:19:23
    统计学期末总复习 题型:10选择7大题 重点,三大抽样分布(第六章往后) 第一章 ...帕累托: 排好序的条形图 累计频数分布: 向上累积和向下累积,很好理解 直方: 用面积代表频率 茎叶: 了解如何读数据
  • PMP项目管理概念精讲

    2018-09-28 21:05:09
    直方,是一种特殊形式的条形图,用于描述集中趋势、分散程度和统计分布形状。与控制不同,直方不考虑时间对分布内变化影响。 控制,用来确定一个过程是否稳定,或者是否具有可预测绩效。根据...
  • 用Excel做直方(2):频率分布直方

    万次阅读 多人点赞 2019-03-23 17:02:54
    直方是一种条形图,是以组距为底边、以频数为高度一系列连接起来直方型矩形 2、相关概念 组数:在统计数据时,把数据按照不同范围分成几个组,分成个数称为组数。 组距:每一组两个端点差 ...
  • 通过前面几篇博客大致内容,我们也能大致学会绘制图像,然后在我们做数据分析,统计分析时候,我们需要用特定图像来展示特定数据,从而达到可视化效果,让结果更加直观,这篇博客我将会详细介绍一下每一种...
  • 二、常用统计图对比 折线图 特点:能够显示数据变化趋势,反映事物变化情况。(变化) 直方图 一般用横轴表示数据范围,纵轴表示分布情况。 特点:绘制连续性数据,展示一组或者多组数据分布状况(统计) ...
  • 初入统计学 day1

    2019-03-02 15:21:24
    初入统计学 day1 统计学中一些基本概念介绍 常用统计数 中位数 众数 平均数(μ\...条形图 折线 饼图接触比较多,这里不再一一介绍 线型 茎叶 统计: 样本和总体: 总体:代表所研究对象全体,例如1....
  • 将 Python 用于介绍性数据科学概念的示例 课程大纲 第一阶段:介绍 阶段 2:描述数据 将原始数据加载到数据结构中 计算描述性统计数据 数数 总和或总计 平均值或平均值 最大、最小 测验 阶段 3:数据函数 清理数据 ...
  • 统计学(一)

    2014-04-13 21:05:41
    条形图:垂直和水平,堆积条形图(比较频数)和分段条形图(同时表示频数和百分数) 直方:分组数据,考虑直方,注意等宽与不等宽时(頻率密度),始终记住面积与频数成正比即面积=频数,先求宽度(组距)再求...
  • 第一章 数据分析基本概念与matplotlib绘图模块 1.了解matplotlib、numpy、pandas在数据分析中各自功能: ...2. 数据分析基本概念:把大量数据进行统计整理,得出结果,为后续决策提供数据支持。另外对...
  • ES-聚合

    2021-01-18 19:55:49
    ElasticSearch学习记录聚合高阶概念桶指标桶和指标组合尝试聚合添加度量指标嵌套桶最后修改,再嵌套条形图按时间统计返回空Buckets限定范围聚合过滤和聚合过滤过滤桶后过滤器小结多桶排序内置排序按度量排序...
  • 统计学Task01

    2019-08-05 17:39:30
    象形统计图条形图、线形图、饼图、茎叶图、箱线图 二项分布: 二项分布是由伯努利提出的概念,指的是重复n次独立的伯努利试验。在每次试验中只有两种可能的结果,而且两种结果发生与否互相对立,并且相互独立,与...
  • 统计条形图 FBLongPressEmojiPopUp FBShimmerEffect CircularCollectionView PropertyAnimator 刷页 魔术网格 QRMaster StrechyHeaderCollectionView DateGroupMessages MapKitPins DrawingCanvas ...
  • SPSS10.0教程

    2018-01-30 10:03:07
    7.1 相关分析的概念与相关分析过程 7.2 两个变量的相关分析 7.3 偏相关分析 7.4 距离分析 思考题 第8章 均值比较与T检验 导言 8.1 均值比较与均值比较的检验过程 8.2 单样本T检验 8.3 独立样本T检验 8.4 配对样本T...
  • 包括绪论、VisualC++数字图像处理基础、图像特征、统计模式识别、模式识别决策方法及实现,以及人脸检测与特征点定位、汽车牌照识别、脑部医学影像诊断、印刷体汉字识别、手写体数字识别、一维条形码识别、运动图像...
  • 包括绪论、VisualC++数字图像处理基础、图像特征、统计模式识别、模式识别决策方法及实现,以及人脸检测与特征点定位、汽车牌照识别、脑部医学影像诊断、印刷体汉字识别、手写体数字识别、一维条形码识别、运动图像...
  • 包括绪论、VisualC++数字图像处理基础、图像特征、统计模式识别、模式识别决策方法及实现,以及人脸检测与特征点定位、汽车牌照识别、脑部医学影像诊断、印刷体汉字识别、手写体数字识别、一维条形码识别、运动图像...
  • 6.2 一个简单的条形码打印系统 298 6.3 一维条形识别 312 6.3.1 硬件识别系统 312 6.3.2 预处理过程 312 6.3.3 译码过程 314 6.4 一维条形码识别系统实例 315 6.4.1 DIB.H位图存取头文件 316 6.4.2...

空空如也

空空如也

1 2 3
收藏数 50
精华内容 20
关键字:

条形统计图的概念