图像特效之三角几何应用

简介: 一:基本的三角函数知识 同样根据a, b的值可以计算出角度θ值,称之为反三角函数,角度θ=atan2(a, b) 图像处理中应用三角函数常常把中心点设置为A点,任意像素点B到A的距离可以根据三 角函数来计算得出,常见的计算模型如下: 对待求像素点加以一定三角函数变化,可以...

一:基本的三角函数知识


同样根据a, b的值可以计算出角度θ值,称之为反三角函数,角度θ=atan2(a, b)

图像处理中应用三角函数常常把中心点设置为A点,任意像素点B到A的距离可以根据三

角函数来计算得出,常见的计算模型如下:


对待求像素点加以一定三角函数变化,可以实现很多意想不到的图形特效,中心像素点可以

通过以下计算获得

int centerX = width/2;

int centerY = height/2;

扫描到的像素点p(x, y)可以基于 中心像素点,角度θ,两点之间距离Radius可以通过如

下计算获得:

int trueX = col -centerX;

int trueY = row -centerY;

theta = Math.atan2((trueY),(trueX));

radius = Math.sqrt(trueX*trueX + trueY*trueY);

二:特效原理

实现的特效很简单,上述的三角几何中计算结果中,有两个可以改变其值再重新计算坐标

P(x,y)。一个是角度,另外一个是半径距离,分别对角度与距离加以一定权重值计算,得到

如下两种特效:

1.  哈哈镜效果,主要是改变半径值,计算方法如下:

double newRadius = Math.sqrt(radius) * factor;

newX = centerX + (newRadius * Math.cos(theta));

newY = centerY + (newRadius * Math.sin(theta));

其中factor为输入参数

 

2.  中心螺旋效果,主要是改变角度θ的值,计算方法如下:

newX = centerX + (radius * Math.cos(theta+degree * radius));

newY = centerY + (radius * Math.sin(theta+degree * radius));

其中degree为输入参数.


三:程序效果

哈哈镜效果:


螺旋效果


两个滤镜程序的源代码如下:

1. Magic Mirror

package com.process.blur.study;

import java.awt.image.BufferedImage;

public class MagicMirrorFilter extends AbstractBufferedImageOp {
	private double factor = 15.0d; // default value
	
	public MagicMirrorFilter() {
		
	}
	
	public MagicMirrorFilter(double factor) {
		this.factor = factor;
	}

	public double getFactor() {
		return factor;
	}

	public void setFactor(double factor) {
		this.factor = factor;
	}

	@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];
        int[] outPixels = new int[width*height];
        getRGB( src, 0, 0, width, height, inPixels );
        int index = 0, outIndex = 0;
        int centerX = width/2;
    	int centerY = height/2;
    	double theta, radius;
    	double newX, newY;
    	int offsetX = 0, offsetY = 0;
        for(int row=0; row<height; row++) {
        	int ta = 0, tr = 0, tg = 0, tb = 0;
        	for(int col=0; col<width; col++) {

    			int trueX = col - centerX;
    			int trueY = row - centerY;
    			theta = Math.atan2((trueY),(trueX));
    			radius = Math.sqrt(trueX*trueX + trueY*trueY);
    			double newRadius = Math.sqrt(radius) * factor;
    			newX = centerX + (newRadius * Math.cos(theta));
    			newY = centerY + (newRadius * Math.sin(theta));
    			
    			if (newX > 0 && newX < width) {
    				offsetX = (int)newX;
    			} else {
    				newX = 0;
    			}
    			
    			if (newY > 0 && newY < height) {
    				offsetY = (int)newY;
    			} else {
    				newY = 0;
    			}
    			
        		index = offsetY * width + offsetX;
        		ta = (inPixels[index] >> 24) & 0xff;
                tr = (inPixels[index] >> 16) & 0xff;
                tg = (inPixels[index] >> 8) & 0xff;
                tb = inPixels[index] & 0xff;
    			
    			// use newX, newY and fill the pixel data now...
                outIndex = row * width + col;
                outPixels[outIndex] = (ta << 24) | (tr << 16) | (tg << 8) | tb;
        	}
        }

        setRGB( dest, 0, 0, width, height, outPixels );
        return dest;
	}

}
2. Swirl
package com.process.blur.study;

import java.awt.image.BufferedImage;

public class SwirlFilter extends AbstractBufferedImageOp{

	// recommended scope is [0.1 ~ 0.001]
	private double degree = 0.02d; // default value, 
	
	public SwirlFilter() {
		
	}
	
	public double getDegree() {
		return degree;
	}

	public void setDegree(double degree) {
		this.degree = degree;
	}

	@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];
        int[] outPixels = new int[width*height];
        getRGB( src, 0, 0, width, height, inPixels );
        int index = 0, outIndex = 0;
        int centerX = width/2;
    	int centerY = height/2;
    	double theta, radius;
    	double newX, newY;
    	int offsetX = 0, offsetY = 0;
        for(int row=0; row<height; row++) {
        	int ta = 0, tr = 0, tg = 0, tb = 0;
        	for(int col=0; col<width; col++) {

    			int trueX = col - centerX;
    			int trueY = row - centerY;
    			theta = Math.atan2((trueY),(trueX));
    			radius = Math.sqrt(trueX*trueX + trueY*trueY);
    			
    			// the top trick is to add (degree * radius), generate the swirl effect...
    			newX = centerX + (radius * Math.cos(theta + degree * radius));
    			newY = centerY + (radius * Math.sin(theta + degree * radius));
    			
    			if (newX > 0 && newX < width) {
    				offsetX = (int)newX;
    			} else {
    				offsetX = col;
    			}
    			
    			if (newY > 0 && newY < height) {
    				offsetY = (int)newY;
    			} else {
    				offsetY = row;
    			}
    			
        		index = offsetY * width + offsetX;
        		ta = (inPixels[index] >> 24) & 0xff;
                tr = (inPixels[index] >> 16) & 0xff;
                tg = (inPixels[index] >> 8) & 0xff;
                tb = inPixels[index] & 0xff;
    			
    			// use newX, newY and fill the pixel data now...
                outIndex = row * width + col;
                outPixels[outIndex] = (ta << 24) | (tr << 16) | (tg << 8) | tb;
        	}
        }

        setRGB( dest, 0, 0, width, height, outPixels );
        return dest;
	}

}
转载文章请务必注明出处

目录
相关文章
|
小程序 人工智能
|
机器学习/深度学习 人工智能 自然语言处理
【ACL2024】基于长尾检索知识增强的大语言模型
近日,阿里云人工智能平台PAI与阿里集团安全部内容安全算法团队、华东师范大学何晓丰教授团队合作,在自然语言处理顶级会议ACL2024上发表论文《On the Role of Long-tail Knowledge in Retrieval Augmented Large Language Models》,论文主题为长尾知识检索增强的大语言模型。通过将问题识别为普通可回答和长尾两种性质,让大模型针对性的对长尾问题进行检索文档增强。对于普通可回答的用户提问可以直接通过大模型回答,而不需要进行文档检索增强,从而能增强大模型处理不同类型用户提问的效率。
|
API 数据安全/隐私保护 开发者
用 Python 优雅地玩转 Elasticsearch:实用技巧与最佳实践
用 Python 优雅地玩转 Elasticsearch:实用技巧与最佳实践
|
11月前
|
XML 数据格式 索引
xpath模块使用教程
XPath 是一种在 XML 文档中查找信息的语言,广泛用于 HTML 解析。本文介绍了 XPath 的安装与使用,包括 lxml 库的安装、解析流程、基本语法、路径表达式、谓语、通配符、多路径选择、逻辑运算、属性查询、索引查询、模糊查询、内容查询、属性值获取及节点内容转换等。通过实例详细说明了各种用法,帮助读者快速掌握 XPath 的应用技巧。
758 39
|
10月前
|
移动开发 前端开发 Java
|
11月前
|
机器学习/深度学习 自然语言处理
完全使用自生成数据实现LLM自我纠正,DeepMind新突破SCoRe:纠正性能提升15.9%
【10月更文挑战第27天】Google DeepMind 研究人员开发了 SCoRe 方法,利用多回合在线强化学习显著提升大型语言模型(LLM)的自我纠正能力。该方法分为两个阶段:第一阶段通过强化学习减少行为崩溃,第二阶段使用奖励塑造优化两次尝试的性能。实验结果显示,SCoRe 在数学和编程任务上分别提升了 4.4% 和 12.2% 的自我纠正性能。
263 3
|
12月前
|
JSON 数据可视化 API
玩转数据科学:Python实战分析天气预报变动趋势
【10月更文挑战第1天】随着气候变化对日常生活的影响日益显著,理解和预测天气模式变得越来越重要。本文将引导您如何使用Python来抓取和分析天气预报数据,从而揭示天气变化的趋势。我们将介绍从获取公开气象API的数据到清洗、处理以及可视化整个过程的技术方法。
757 2
|
负载均衡 Cloud Native 容灾
阿里云负载均衡SLB价格_ALB、NLB和CLB区别_负载均衡详细介绍
阿里云负载均衡SLB提供ALB、NLB和CLB三种类型,分别适用于7层和4层的不同场景。ALB与NLB仅支持按量付费,而CLB则额外提供包年包月选项。ALB强调7层应用处理与高级路由,NLB聚焦4层的大流量处理与SSL卸载。两者均支持自动弹性伸缩,确保高可用性和性能。CLB作为传统负载均衡,适用于特定需求。每种类型依据实例规格与使用量收费,其中公网实例还需支付网络费用。通过这些服务,用户可以实现流量分发、故障转移及提升应用系统的稳定性和扩展性。
|
Web App开发 存储 运维
即学即会 Serverless | 初识 Serverless
Serverless 架构被越来越多的业务所采纳,成为其技术选型,大多数开发者已经跨越对 Serverless 概念了解,切实向落地实践出发。本文带大家一探究竟,为什么说 Serverless 可以帮助开发者聚焦核心业务价值,以及有哪些场景更适合 Serverless 架构!
|
存储 并行计算 PyTorch
社区供稿 | 10G显存,通义千问-7B-int4消费级显卡最佳实践
在魔搭社区,通义千问团队发布了Qwen-7B-Chat的Int4量化模型,Qwen-7B-Chat-Int4。该方案的优势在于,它能够实现几乎无损的性能表现,模型大小仅为5.5GB,内存消耗低,速度甚至超过BF16。