热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

java图像识别出距离_java图像处理之倒角距离变换

图像处理中的倒角距离变换(ChamferDistanceTransform)在对象匹配识别中经常用到,算法基本上是基于3x3的窗口来生成每个像素的距离值,

图像处理中的倒角距离变换(Chamfer Distance Transform)在对象匹配识别中经常用到,算法基本上是基于3x3的窗口来生成每个像素的距离值,分为两步完成距离变换,第一步从左上角开始,从左向右、从上到下移动窗口扫描每个像素,检测在中心像素x的周围0、1、2、3四个像素,保存最小距离与位置作为结果,图示如下:

4125d6163cf748e49e65af6e0f13b86a.png

第二步从底向上、从右向左,对每个像素,检测相邻像素4、5、6、7保存最小距离与位置作为结果,如图示所:

7001d9b0851d0b06127ad8f2491d8824.png

完成这两步以后,得到的结果输出即为倒角距离变换的结果。完整的图像倒角距离变换代码实现可以分为如下几步:

1.对像素数组进行初始化,所有背景颜色像素点初始距离为无穷大,前景像素点距离为0

2.开始倒角距离变换中的第一步,并保存结果

3.基于第一步结果完成倒角距离变换中的第二步

4.根据距离变换结果显示所有不同灰度值,形成图像

最终结果显示如下(左边表示原图、右边表示CDT之后结果)

10d2d2398d651753a2388cac6e8172b2.png

完整的二值图像倒角距离变换的源代码如下:

package com.gloomyfish.image.transform;

import java.awt.Color;

import java.awt.image.BufferedImage;

import java.util.Arrays;

import com.gloomyfish.filter.study.AbstractBufferedImageOp;

public class CDTFilter extends AbstractBufferedImageOp {

private float[] dis; // nn-distances

private int[] pos; // nn-positions, 32 bit index

private Color bakcgroundColor;

public CDTFilter(Color bgColor)

{

this.bakcgroundColor = bgColor;

}

@Override

public BufferedImage filter(BufferedImage src, BufferedImage dest) {

int width = src.getWidth();

int height = src.getHeight();

if (dest == null)

dest = createCompatibleDestImage(src, null);

int[] inPixels = new int[width * height];

pos = new int[width * height];

dis = new float[width * height];

src.getRGB(0, 0, width, height, inPixels, 0, width);

// 随机生成距离变换点

int index = 0;

Arrays.fill(dis, Float.MAX_VALUE);

int numOfFC = 0;

for (int row = 0; row

for (int col = 0; col

index = row * width + col;

if (inPixels[index] != bakcgroundColor.getRGB()) {

dis[index] = 0;

pos[index] = index;

numOfFC++;

}

}

}

final float d1 = 1;

final float d2 = (float) Math.sqrt(d1 * d1 + d1 * d1);

System.out.println(numOfFC);

float nd, nd_tmp;

int i, in, cols, rows, nearestPixel;

// 1 2 3

// 0 i 4

// 7 6 5

// first pass: forward -> L->R, T-B

for (rows = 1; rows

for (cols = 1; cols

i = rows * width + cols;

nd = dis[i];

nearestPixel = pos[i];

if (nd != 0) { // skip background pixels

in = i;

in += -1; // 0

if ((nd_tmp = d1 + dis[in])

nd = nd_tmp;

nearestPixel = pos[in];

}

in += -width; // 1

if ((nd_tmp = d2 + dis[in])

nd = nd_tmp;

nearestPixel = pos[in];

}

in += +1; // 2

if ((nd_tmp = d1 + dis[in])

nd = nd_tmp;

nearestPixel = pos[in];

}

in += +1; // 3

if ((nd_tmp = d2 + dis[in])

nd = nd_tmp;

nearestPixel = pos[in];

}

dis[i] = nd;

pos[i] = nearestPixel;

}

}

}

// second pass: backwards -> R->L, B-T

// exactly same as first pass, just in the reverse direction

for (rows = height - 2; rows >= 1; rows--) {

for (cols = width - 2; cols >= 1; cols--) {

i = rows * width + cols;

nd = dis[i];

nearestPixel = pos[i];

if (nd != 0) {

in = i;

in += +1; // 4

if ((nd_tmp = d1 + dis[in])

nd = nd_tmp;

nearestPixel = pos[in];

}

in += +width; // 5

if ((nd_tmp = d2 + dis[in])

nd = nd_tmp;

nearestPixel = pos[in];

}

in += -1; // 6

if ((nd_tmp = d1 + dis[in])

nd = nd_tmp;

nearestPixel = pos[in];

}

in += -1; // 7

if ((nd_tmp = d2 + dis[in])

nd = nd_tmp;

nearestPixel = pos[in];

}

dis[i] = nd;

pos[i] = nearestPixel;

}

}

}

for (int row = 0; row

for (int col = 0; col

index = row * width + col;

if (Float.MAX_VALUE != dis[index]) {

int gray = clamp((int) (dis[index]));

inPixels[index] &#61; (255 <<24) | (gray <<16) | (gray <<8)

| gray;

}

}

}

setRGB(dest, 0, 0, width, height, inPixels);

return dest;

}

private int clamp(int i) {

return i > 255 ? 255 : (i <0 ? 0 : i);

}

}

以上就是本文的全部内容&#xff0c;希望对大家的学习有所帮助&#xff0c;也希望大家多多支持脚本之家。



推荐阅读
  • 深入解析 Android IPC 中的 Messenger 机制
    本文详细介绍了 Android 中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。 ... [详细]
  • 深入解析Java枚举及其高级特性
    本文详细介绍了Java枚举的概念、语法、使用规则和应用场景,并探讨了其在实际编程中的高级应用。所有相关内容已收录于GitHub仓库[JavaLearningmanual](https://github.com/Ziphtracks/JavaLearningmanual),欢迎Star并持续关注。 ... [详细]
  • 深入理解Java多线程并发处理:基础与实践
    本文探讨了Java中的多线程并发处理机制,从基本概念到实际应用,帮助读者全面理解并掌握多线程编程技巧。通过实例解析和理论阐述,确保初学者也能轻松入门。 ... [详细]
  • Redux入门指南
    本文介绍Redux的基本概念和工作原理,帮助初学者理解如何使用Redux管理应用程序的状态。Redux是一个用于JavaScript应用的状态管理库,特别适用于React项目。 ... [详细]
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • 本文探讨了在 SQL Server 中使用 JDBC 插入数据时遇到的问题。通过详细分析代码和数据库配置,提供了解决方案并解释了潜在的原因。 ... [详细]
  • 深入解析Java多线程与并发库的应用:空中网实习生面试题详解
    本文详细探讨了Java多线程与并发库的高级应用,结合空中网在挑选实习生时的面试题目,深入分析了相关技术要点和实现细节。文章通过具体的代码示例展示了如何使用Semaphore和SynchronousQueue来管理线程同步和任务调度。 ... [详细]
  • 本文介绍了SVD(奇异值分解)和QR分解的基本原理及其在Python中的实现方法。通过具体代码示例,展示了如何使用这两种矩阵分解技术处理图像数据和计算特征值。 ... [详细]
  • 实用正则表达式有哪些
    小编给大家分享一下实用正则表达式有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下 ... [详细]
  • 探讨如何修复Visual Studio Code中JavaScript的智能感知和自动完成功能在特定场景下无法正常工作的问题,包括配置检查、语言模式选择以及类型注释的使用。 ... [详细]
  • 本文探讨了为何相同的HTTP请求在两台不同操作系统(Windows与Ubuntu)的机器上会分别返回200 OK和429 Too Many Requests的状态码。我们将分析代码、环境差异及可能的影响因素。 ... [详细]
  • 深入解析SpringMVC核心组件:DispatcherServlet的工作原理
    本文详细探讨了SpringMVC的核心组件——DispatcherServlet的运作机制,旨在帮助有一定Java和Spring基础的开发人员理解HTTP请求是如何被映射到Controller并执行的。文章将解答以下问题:1. HTTP请求如何映射到Controller;2. Controller是如何被执行的。 ... [详细]
  • 本文回顾了2017年的转型和2018年的收获,分享了几家知名互联网公司提供的工作机会及面试体验。 ... [详细]
  • 为了解决不同服务器间共享图片的需求,我们最初考虑建立一个FTP图片服务器。然而,考虑到项目是一个简单的CMS系统,为了简化流程,团队决定探索七牛云存储的解决方案。本文将详细介绍使用七牛云存储的过程和心得。 ... [详细]
  • 本文探讨了图像标签的多种分类场景及其在以图搜图技术中的应用,涵盖了从基础理论到实际项目实施的全面解析。 ... [详细]
author-avatar
笑眯眯马甲61
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有