本文讲述了java获取彩色图像中的主色彩的实例代码。分享给大家供大家参考,具体如下:

一:基本思路

对于一张rgb色彩空间的彩色图像,很多时间我们想通过程序获得该图像有几种主要的色彩,但是对一般图像来说,在色彩交界处都是通过像素混合来实现自然过渡,所以直接扫描图像的像素值,得到的不同颜色值可能多达上百中,而实际上图像可能只有3~4种的主要色彩,如何去掉那些混合颜色,准确提取出来这3~4中的主色彩,根据一般图像的特征,图像在不同色彩的边界处混合不同的颜色值,此可以视为图像的边缘特性之一,因此可以根据简单的边缘梯度算法实现这些混合像素的提取得到输出的像素值数组,然后扫描每个像素值,寻找指定半径参数r周围的像素,发现为零,而且距离中心像素最近的像素点的值做为中心像素的像素值,扫描结束以后输出像素数组,然后对数组线性扫描,即可得到图片的主要色彩rgb值。

二:实现步骤

1.      输入图像数组,对彩色图像灰度化;

2.      对灰度化以后的图像,计算图像梯度,这里使用sobol算子;

3.      对得到每一个非零像素点实现半径为r的范围内的扫描,找出与之最相近的为零的原像素值;

4.      对得到数组进行简单的扫描,得到主色彩。

其中参数r是要根据不同应用场景,找到最合适的值。理论上图像越大,r的取值也应该越大,否则算法会失准。

三:原图及运行效果

原图

算法运行之后提取到四种主要色彩

四:算法实现源代码

public static bufferedimage removeblendpixels(bufferedimage image, int raidus) {

int width = image.getwidth();

int height = image.getheight();

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

getrgb(image, 0, 0, width, height, pixels);

// 创建处理结果

bufferedimage resultimg = createcompatibledestimage(image, null);

setrgb(resultimg, 0, 0, width, height, pixels);

// 灰度化与梯度求取

byte[] graydata = getgraydata(pixels, width, height);

byte[] binarydata = getgrident(graydata, width, height);

int index = 0;

for (int row = 1; row < height - 1; row++) {

for (int col = 1; col < width - 1; col++) {

index = row * width + col;

int pixel = (binarydata[index] & 0xff);

if (pixel > 0) {

// 半径扫描操作

int mindis = integer.max_value;

int minrow = -1;

int mincol = -1;

int nr = 0;

int nc = 0;

int index2 = 0;

for (int subrow = -raidus; subrow <= raidus; subrow++) {

nr = row + subrow;

if (nr < 0 || nr >= height) {

continue;

}

for (int subcol = -raidus; subcol <= raidus; subcol++) {

nc = col + subcol;

if (nc < 0 || nc >= width) {

continue;

}

index2 = nr * width + nc;

int value = (binarydata[index2] & 0xff);

if (value == 0) {

int distance = distancecolor(image.getrgb(nc, nr), image.getrgb(col, row));

if (distance < mindis) {

mindis = distance;

minrow = nr;

mincol = nc;

}

}

}

}

resultimg.setrgb(col, row, image.getrgb(mincol, minrow));

}

}

}

return resultimg;

}

public static int distancecolor(int rgb, int rgb2) {

// color one

int r1 = (rgb >> 16) & 0xff;

int g1 = (rgb >> 8) & 0xff;

int b1 = rgb & 0xff;

// color two

int r2 = (rgb2 >> 16) & 0xff;

int g2 = (rgb2 >> 8) & 0xff;

int b2 = rgb2 & 0xff;

// distance

int rr = r1 - r2;

int gg = g1 - g2;

int bb = b1 - b2;

int sum = (int) math.sqrt(rr * rr + gg * gg + bb * bb);

return sum;

}

public static byte[] getgraydata(int[] inpixels, int width, int height) {

// 图像灰度化

byte[] outpixels = new byte[width * height];

int index = 0;

for (int row = 0; row < height; row++) {

int tr = 0, tg = 0, tb = 0;

for (int col = 0; col < width; col++) {

index = row * width + col;

tr = (inpixels[index] >> 16) & 0xff;

tg = (inpixels[index] >> 8) & 0xff;

tb = inpixels[index] & 0xff;

int gray = (int) (0.299 * tr + 0.587 * tg + 0.114 * tb);

outpixels[index] = (byte) (gray & 0xff);

}

}

return outpixels;

}

public static byte[] getgrident(byte[] inpixels, int width, int height) {

byte[] outpixels = new byte[width * height];

int index = 0;

for (int row = 0; row < height; row++) {

int tr = 0;

for (int col = 0; col < width; col++) {

if (row == 0 || col == 0 || (row == height - 1) || (col == width - 1)) {

index = row * width + col;

outpixels[index] = (byte) (0x00);

continue;

}

int xg = 0, yg = 0;

for (int sr = -1; sr <= 1; sr++) {

for (int sc = -1; sc <= 1; sc++) {

int nrow = row + sr;

int ncol = col + sc;

if (nrow < 0 || nrow >= height) {

nrow = 0;

}

if (ncol < 0 || ncol >= width) {

ncol = 0;

}

index = nrow * width + ncol;

tr = (inpixels[index] & 0xff);

xg += x_sobel[sr + 1][sc + 1] * tr;

yg += y_sobel[sr + 1][sc + 1] * tr;

}

}

index = row * width + col;

int g = (int) math.sqrt(xg * xg + yg * yg);

outpixels[index] = (byte) (clamp(g) & 0xff);

}

}

return outpixels;

}

需要定义的常量值如下:

public static final int[][] x_sobel = new int[][] { { -1, -2, -1 }, { 0, 0, 0 }, { 1, 2, 1 } };

public static final int[][] y_sobel = new int[][] { { -1, 0, 1 }, { -2, 0, 2 }, { -1, 0, 1 } };

public static final int block_pixel_radius = 5;

梯度求取使用是sobol算子,对处理以后的bufferedimage对象扫描获取主色彩的代码如下:

int width = result.getwidth();

int height = result.getheight();

map colorindexmap = new hashmap();

for (int row = 0; row < height; row++) {

for (int col = 0; col < width; col++) {

int pixelvalue = result.getrgb(col, row);

if (!colorindexmap.containskey(pixelvalue)) {

colorindexmap.put(pixelvalue, pixelvalue);

}

}

}

// now scan pixel value

// return result

system.out.println("number of color = " + colorindexmap.size());

return colorindexmap.keyset().toarray(new integer[0]);

测试代码如下:

public static void main(string[] args) {

file file = new file("d:\\gloomyfish\\bigmonkey.png");

file resultfile = new file("d:\\gloomyfish\\result.png");

try {

bufferedimage image = imageio.read(file);

bufferedimage result = removeblendpixels(image, block_pixel_radius);

imageio.write(result, "png", resultfile);

integer[] colors = extractcolors(result);

system.out.println("total colors : " + colors.length);

} catch (ioexception e) {

e.printstacktrace();

}

}

注意:主要的关键在于对待处理图像输入正确大小的半径,这个半径大小跟图像实际大小相关,而且算法可以近一步优化成不依赖半径参数的版本,知道找到等于零的像素为止。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持萬仟网。

希望与广大网友互动??

点此进行留言吧!

java获取图片主色_Java获取彩色图像中的主色彩的实例代码相关推荐

  1. java get null_java 获取对象中为null的字段实例代码

    下面一段简单的代码给大家分享java 获取对象中为null的字段,具体代码如下所述: private static String[] getNullPropertyNames(Object sourc ...

  2. java获取图片rgb值_Java 之 获取图片主色调

    public classHslTest {/*** 获取图片主色调的rgb值 *@parampath *@return*@throwsException*/ public static RGB get ...

  3. 如何获取彩色图像中的主色彩

    一:基本思路 对于一张RGB色彩空间的彩色图像,很多时间我们想通过程序获得该图像有几种主要的色彩,但是对一般图像来说,在色彩交界处都是通过像素混合来实现自然过渡,所以直接扫描图像的像素值,得到的不同颜 ...

  4. java 获取手机归属地_java 获取手机归属地

    java 获取手机归属地 [2021-01-30 20:46:44]  简介: php去除nbsp的方法:首先创建一个PHP代码示例文件:然后通过"preg_replace("/( ...

  5. java 一周前日期_java获取当前时间前一周、前一月、前一年的时间

    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Calendar c = Calend ...

  6. java 优酷视频缩略图_java获取优酷等视频缩略图

    类型:Android平台大小:6.8M语言:中文 评分:7.2 标签: 立即下载 想获取优酷等视频缩略图,在网上没有找到满意的资料,参考了huangdijia的PHP版工具一些思路,写了下面的JAVA ...

  7. java生成随机数的方法_Java获取随机数的3种方法

    随机数在实际中使用很广泛,比如要随即生成一个固定长度的字符串.数字.或者随即生成一个不定长度的数字.或者进行一个模拟的随机选择等等.Java提供了最基本的工具,可以帮助开发者来实现这一切. 一.Jav ...

  8. java获取当前年月日历_java获取当前年份、月份和日期字符串等

    Java获取当前年份.月份和日期是通过Calendar类的实例对象来获取的. 首先创建一个Calendar类的实例对象,Calendar类属于java.util包. Calendar calendar ...

  9. android获取图片缩略图,Android系获取图片和视频的缩略图

    获取手机里视频缩略图: public static Bitmap getVideoThumbnail(ContentResolver cr,Uri uri) { Bitmap bitmap = nul ...

最新文章

  1. 并发、并行、串行、同步、异步、阻塞、非阻塞
  2. GAITC 2021智媒论坛丨曹立宏:AI和BI互助发展 智能媒体任重道远
  3. 谱减法降噪的matlab代码实现
  4. 怎么切换用户_走进通信:4G手机跟基站是怎么“交流”的
  5. 基于ncat的简易web服务器
  6. 假设检验在数据分析中的应用
  7. Fanout交换器-搭建环境
  8. 创建线程的第二种方法(实现Runnable接口)
  9. MongoDB语法学习
  10. React学习笔记二 通过柯里化函数实现带参数的事件绑定
  11. 在Maple 9中察看内置函数的原代码的三种方法
  12. 通过javascritp对表格进行列拖动排序
  13. 栈-剑指 Offer 30. 包含min函数的栈
  14. doc,excel,ppt转存pdf并预览
  15. 案例|工业物联网解决方案•污水处理厂智能监控运维云平台
  16. 满减折扣促销功能代码优化实战
  17. Java杂谈——求所有的4位吸血鬼数字
  18. Java面试之场景题汇总
  19. html中鱼眼效果,鱼眼效果和放大效果怎么做
  20. 据我爱无人机网两家国外公司合作开展无人机货运服务

热门文章

  1. 软件测试 - 缺陷管理
  2. heywhale数据结构学习--线性表
  3. pythonocc_pythonOCC例子搬运:4.经典瓶子造型
  4. kotlin 图片浮雕处理
  5. 我在亚信实习的日记(结束)
  6. Zeal下载安装及使用步骤(图文详解)
  7. 三本计算机和专科,三本与专科院校到底有什么区别?
  8. Next middleware
  9. IO虚拟化 - vitio-blk后端驱动分析【转】
  10. jQuery前端验证(四)