- 浏览: 676752 次
- 性别:
- 来自: 合肥
文章分类
最新评论
-
di1984HIT:
学习了,学习了!
Tomcat的URL中文乱码解决以及传输优化 -
arottenapple:
...
我的二十一天CoreJava 学习笔记 -
黯淡流觞:
...
我的二十一天CoreJava 学习笔记 -
onlyOneToOne:
wsc830719 写道@RequestMapping(val ...
spring mvc3中 ResponseBody中文乱码 -
waj_615:
但是打印订单不是简单的string 啊
用java实现打印功能
受朋友之托,做了一个小软件。只是一个练手,现将思路重现。
需求
模拟一工厂在生产瓶盖,机器是自动为盖子上色。在上色后,要检查瓶盖是否上色正常。
把9个瓶盖成宫形排列,并依次编号。
要求软件,给定一个其准的瓶盖图片,再给一张9个瓶盖的排列图片,判断在图片是有哪几个编号的瓶盖是没有正常上色的。
基准图片
生产图片
在软件中输入这两张图片后能显示第2和5号瓶盖有错误。
最终效果
OK,好,开始解决。
分析
- 判断标准
从所给的图片分析,虽然我们人眼能一眼就看出瓶盖的大小形状和颜色,但机器并不知道。我们要确定一个判断的标准。因为从所给的图片来看,如果判断形状那太麻烦,而且我们可以看出,不同瓶盖之间的颜色差距是非常大的,那么通过颜色来判断就会容易的多。但对于颜色,我们又要再深入考虑。我们的第一反应,如果使用颜色来比较的话那就使用RGB来判断(后面会以另一种方案来实现),但颜色的组成中的值非常的敏感,同种颜色在不同光线中,甚至于同一张照片在不同的时间其RGB颜色都会有很大的差距。不过,这是一个方向,先定下,以颜色来判断,颜色不以一个点,而是以一个区域中的GRB不同颜色的范围值。
- 操作步骤
选择基准图片
缩放图片到固定尺寸(并显示在界面中)
从基准图片中分析出颜色范围
选择检查图片
缩放图片到固定尺寸(并显示在界面中)
把检查图片分割成9份
循环判断9份的小图片的颜色是否与基准颜色相同
输出不合格的编号(在界面中显示)
- 分析基准图片
从图片中可以看出,并不是一张纯色的图片,根据实际情况,我们将选择图片中的内切矩形中的点来综合判断,为快速测试,先用取色器取出RGB颜色,大约B在170以上,R在60以下,G在120左右(后面会发现这种判断真是惨不忍睹)。
- 分析判断切割后的小图片
切割后的图片中的瓶盖位置应该和基准图中的位置差不多,除非是图片拍歪了。要判断是否相同,也是只取圆中的内切矩形的一切颜色来判断。要考虑容错,就像图片中的第4和7号中间被曝光的太严重,在这两个瓶盖中肯定会有大量的白色。把容错值考虑为0.8,也就是在这个矩形中只要有80%的颜色在合格范围内就算合格。(我想当然了,后面的测试证明容错即使是0.4都很吃力)
修正错误
如果按以上的判断方法也可判断出来,但结果就是准确率很低,要求所拍的照片不能有曝光,颜色要正等等。在网上搜索了些信息,得到了另一个有用的信息。那就是HSB,对于RGB来说,颜色变一点点其值就变化的很大,但对于HSB来说,同一颜色的色相度非常的稳定,误差也不会超过0.1,在换成HSB判断后,准确率非常的高,判断时不必再用内切矩形,而是整个小图片,这时的容错值可达到70%以上,就是说在包含了小图片中后面的桌子背景的错误颜色后,它都还能有70%的点是判断正确,实在是很不错。下面就以HSB的判断为准来显示代码。
开始编程
先不用界面,基准图的颜色用取色器取出RGB,再换算成HSB,对应的色相度在0.5到0.6。
先创建一个类起名为Pic,把main方法中的结构做出来,测试两张不同的3*3瓶盖图片
public static void main(String[] args) throws Exception { String path1 = Pic.class.getClassLoader().getResource("resource/1.jpg").getFile(); String path2 = Pic.class.getClassLoader().getResource("resource/2.jpg").getFile(); System.out.println(new File(path1).getParent()); System.out.println("测试" + path1); new Pic().testPic(path1); System.out.println(); System.out.println("测试" + path2); new Pic().testPic(path2); }
再来实现testPIc方法,这个方法里我们来分成几步,读取图片,缩放图片,切割图片,判断不合格图片,显示结果
public void testPic(String imgPath) throws IOException { BufferedImage read = ImageIO.read(new File(imgPath)); BufferedImage fixPic = fixPic(read, 350, 350); List<BufferedImage> list = getPicList(fixPic); List<Integer> indexList = getErrorPicIndex(list, 0.5f, 0.6f); if (indexList.isEmpty()) { System.out.println("测试结果:没有错误"); } else { System.out.print("测试结果:编号"); String index = ""; for (int i = 0; i < indexList.size(); i++) { index += indexList.get(i) + ","; } index.substring(0, index.length() - 1); System.out.println(index + "错误"); } }
实现缩放图片代码,这里在调用的方法里传过来宽度和高度,定的是350*350,
public BufferedImage fixPic(BufferedImage img, int height, int width) { Image scaledInstance = img.getScaledInstance(width, height, Image.SCALE_DEFAULT); BufferedImage newimg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics graphics = newimg.getGraphics(); graphics.drawImage(scaledInstance, 0, 0, null); graphics.dispose(); return newimg; }
实现切割图片方法,把图片切成3*3的9个图片集合
public List<BufferedImage> getPicList(BufferedImage img) { int row = 3, col = 3; List<BufferedImage> list = new ArrayList(); int height = img.getHeight(); int width = img.getWidth(); int drow = height / row; int dcol = width / col; for (int i = 0; i < row; i++) { int y = i * drow; for (int j = 0; j < col; j++) { int x = j * dcol; BufferedImage newimg = new BufferedImage(width / 3, height / 3, BufferedImage.TYPE_INT_RGB); Graphics graphics = newimg.getGraphics(); graphics.drawImage(img, 0, 0, newimg.getWidth(), newimg.getHeight(), x, y, x + dcol, y + drow, null); graphics.dispose(); list.add(newimg); } } return list; }
实现取出不合格图片方法,注意,这里要传两个HSB的H值,也就是我们在上面判断的0.5到0.6在方法体中循环对每个图片进行合格判断
public List<Integer> getErrorPicIndex(List<BufferedImage> list, float min, float max) { ArrayList indexlist = new ArrayList(); for (int i = 0; i < list.size(); i++) { if (!isPass(list.get(i), min, max)) { indexlist.add(i + 1); } } return indexlist; }
实现对图片合格的判断方法,注意,这里的判断是对图片中的每一个点颜色都进行判断,包含了桌面的背景颜色,所有不可能是100%合格,所以这里fex取的是50%合格率,但在测试时发现,合格率可以高达70%以上,所以也可以设置到0.7。
private boolean isPass(BufferedImage img, float min, float max) { int width = img.getWidth(); int height = img.getHeight(); int xbegin = 0; int xend = width; int ybginx = 0; int yend = height; int totleNo = 0, errorNo = 0; for (int i = xbegin; i < xend; i++) { for (int j = ybginx; j < yend; j++) { Color color = new Color(img.getRGB(i, j)); float[] hsb = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null); if (hsb[0] >= min && hsb[0] <= max) { } else { errorNo++; } totleNo++; } } double fex = ((totleNo - errorNo + 0.0) / totleNo); if (fex > 0.5) { return true; } else { return false; } }
好,核心的代码已经完成了。但如果对于界面来说还要一个取基准图片的色相范围的方法。
实现取基准图色相值范围,这里有个思路,怎么来取值。我这么来判断,色相都有一个很小的区间,且变化值不大,值为float类型,基本上都是在小数点后1到2位跳到。那么我把基准图上的所有点的色相值取小数点后1位的整数形,保存到相应下标的数组中,代表的也就是那个色相的小区间(因为是小数点后1位的值),那么再有一个点也是这个区间的,我就把这个数组下标对存的值自增加1。最后就能得到在不同区间中色相的存在分布,因为基准图中大部分都是蓝色,所以取分布值最大的那个数组下标,也就是蓝色所在的色相区间。误差不超过0.1
public float[] getHSBhmn(BufferedImage newImage) { int width = newImage.getWidth(); int height = newImage.getHeight(); int xbegin = 0; int xend = width; int ybegin = 0; int yend = height; float max = 0, maxindex = 0; int[] ints = new int[10]; for (int i = xbegin; i < xend; i++) { for (int j = ybegin; j < yend; j++) { Color color = new Color(newImage.getRGB(i, j)); float[] hsb = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null); ints[(int) (hsb[0] * 10)] = ints[(int) (hsb[0] * 10)] + 1; } } for (int i = 0; i < 10; i++) { if (ints[i] > max) { maxindex = i + 1; max = ints[i]; } } return new float[]{(maxindex - 1) * 0.1f, maxindex * 0.1f}; }
好了,核心代码全部完成。测试,OK。
再就是做界面了,这没什么好写的。用netbeans拖拖画画,简单的就搞定,再加上这个Pic类中的方法代码,一个小软件成型了。
发表评论
-
jetty快速开发时自实现提供jndi服务
2012-07-11 17:21 2201jndi一般是由容器提供,或是启动第三方服务jar包启动。 ... -
spring mvc3中 ResponseBody中文乱码
2012-07-11 14:48 4622使用spring mvc3的@ResponseBody注解以期 ... -
用Java Service Wrapper将java程序制作成系统服务进程
2012-05-23 14:35 10898用途 在做完一个项目程序后,有时会有两种需求想法。 1.在 ... -
linux系统命令备忘
2012-03-13 16:35 863ANT tar -zxvf apache-ant ... -
仿log4j定制自己的Log工具类
2012-03-02 16:27 3410原由: log4j是很强大,可每次使用还要加入log4j包, ... -
自制简易提醒器
2012-02-29 19:50 1312每次烧水和吃饭都忘了时间,就想要一个小闹钟。可网上的软件要不就 ... -
Log4j配置备查
2012-02-29 11:09 1165配置日志信息输出目的地,其语法为: log4j.append ... -
英文版linux下安装中文输入法
2012-02-29 11:01 990首先看一下你的 /var/lib/locales/supp ... -
ubuntu默认禁止root用户登录(备忘)
2012-02-28 11:01 2471ubuntu默认禁止root用户 ... -
WINDOWS下杀死顽固进程命令
2012-02-28 10:59 1791此方法可以杀掉任务管理器杀不掉的进程! 打开cm ... -
读读别人的编程经验
2012-02-28 10:40 9562012-2-28 如何成为一名专家级的开发人员 原 ... -
因练习正则而感受到丰富的解题思路
2011-11-14 15:07 1917不久前,在正则上终于可以登堂入室了,因担心久不练习而使其荒废, ... -
正则研究心得
2011-10-21 16:49 932自己感觉已经在正则上登堂入室了,终于也能体会到它的 ... -
正则表达式截取再整合字符串
2011-10-21 15:44 1454在百度知道中又看到一问题,有意思,可惜 ... -
找出一个字符串中由同一个字符组成的最长子串
2011-10-21 15:15 2057找出一个字符串中由同一个字符组成的最长子串 这是 ... -
设计模式核心笔录
2011-05-25 18:38 1023脑图内容整理成的PD ... -
计算机远程教育视频
2011-05-18 18:37 989由于自己不是正式的计算机专科出来,中途改行做的程序员。虽然在项 ... -
QQlive的缓存提取器
2011-05-11 14:50 2922做为一个程序员就是有这么一个好处,想要有什么样功能的软 ... -
关于unicode编码的研究
2011-03-28 17:24 1104以前写过一篇贴子是写中文在unicode中的编码范围 unic ... -
unicode中的几大区间
2011-03-28 16:31 1871基本平面 平面0 (0000–FFFF): 基本多文种 ...
相关推荐
使用 canvas 识别选择上传图片的主题颜色,获取到出现次数最多的颜色
UIImage分类,包含根据颜色生成图片等功能
利用ajax技术实现无刷新换风格,无刷新切换不同颜色的产品图片 利用ajax技术实现无刷新换风格,无刷新切换不同颜色的产品图片 利用ajax技术实现无刷新换风格,无刷新切换不同颜色的产品图片
将图片加载到内存 循环图片每个像素 找到你需要修改的像素 进行颜色修改。然后再图片BASE64
易语言取图片中指定颜色的坐标源码,取图片中指定颜色的坐标,取设备句柄,取颜色
获取图片中的颜色RGB工具
易语言去掉图片中的颜色文字源码,去掉图片中的颜色文字,黑糊糊
在代码内部动态改变图片颜色,注意:只能改变纯色图片颜色,如图片包含两种及以上颜色,会整个图片的颜色变为相应颜色
android自定义View吸取图片背景的颜色值,获取图片颜色
易语言源码易语言取图片中指定颜色的坐标.rar
简单的C# WinForm颜色填充,操作方法: 鼠标左键在图片上任意点击点,鼠标右键则可把说有的点连接起来并填充指定的颜色。(其实可以用多个曲线组合来填充)
运用jquery提取图片主颜色,自动提取图片的主题颜色,可以运用在图片浏览网站,选取想要的主题颜色图片筛选,用于图片分类,也可以配合图片给出相应的主题颜色,需要在服务器端运行,否则不能呈现效果data-adaptive-...
针对较小size的图片逐点变色,可以是任意RGB色,当然你也可以自己修改代码,让对应的颜色转变为你想要的,代码简单,初学者可以看懂。
取图片中指定颜色的坐标.rar
Js之canvas获取图片主色调,近似色,互补色,以及根据图片颜色获取主题配色方案详解、插件。
主要介绍了Python实现去除图片中指定颜色的像素功能,结合具体实例形式分析了Python基于pil与cv2模块的图形载入、运算、转换等相关操作技巧,需要的朋友可以参考下
delphi图片颜色对比
C#写的提取图片中某种颜色的图案,方便签名提取,需要。运行环境需要netcf支持。
图片上的任何颜色,想改什么颜色就改什么颜色,java 满足你想改的颜色!!!如果不能转换改为下面代码!int pixel = bi.getRGB(i, j)& 0xFFFFFF; if(pixel==pixel1){ bi1.setRGB(i, j, pixel2-16777216); }...
带金属颜色渐变颜色按扭图片