# 图像处理之错切

## 图像处理之错切变换

2016-01-01 08:34:00 weixin_34146986 阅读数 637
• ###### Darknet安装与测试

从理论到实践，快速入门Spring Boot 2.x 从Spring Boot扩展到Spring相关知识的学习和实战 Spring Boot与其他技术框架的集成 Spring Boot部分功能源码解析

23742课时 0分钟 1015人学习 马孔伟
免费试看

P’(x2, y2)当X方向错切变换时：

三：编程关键点解析

Ø  计算错切以后图像的宽与高

double angleValue = (angle/180.0d) * Math.PI;
outh = vertical ? (int)(height + width * Math.tan(angleValue)) : height;
outw = vertical ? width : (int)(width + height * Math.tan(angleValue));
System.out.println("after shear, new width : " + outw);
System.out.println("after shear, new height: " + outh);
Ø  依据目标像素点坐标计算源像素点坐标

double prow = vertical ? row + Math.tan(angleValue) * (col - width) : row;
double pcol = vertical ?

col : col + Math.tan(angleValue) * (row - height); int[] rgb = getPixel(inPixels, width, height, prow, pcol);

Ø  临近点插值计算目标像素点像素值

private int[] getPixel(int[] input, int width, int height,
double prow, double pcol) {
double row = Math.floor(prow);
double col = Math.floor(pcol);
if(row < 0 || row >= height) {
return new int[]{backgroundColor.getRed(),
backgroundColor.getGreen(),
backgroundColor.getBlue()};
}
if(col < 0 || col >= width) {
return new int[]{backgroundColor.getRed(),
backgroundColor.getGreen(),
backgroundColor.getBlue()};
}
double u = vertical ? (prow - row) : pcol - col;
int nextCol = (int)(col + 1);
int nextRow = (int)(row + 1);
if((col + 1) >= width) {
nextCol = (int)col;
}
if((row + 1) >= height) {
nextRow = (int)row;
}
int index1 = (int)(row * width + col);
int index2 = vertical ? (int)(nextRow * width + col) : (int)(row * width + nextCol);

int tr1, tr2;
int tg1, tg2;
int tb1, tb2;

tr1 = (input[index1] >> 16) & 0xff;
tg1 = (input[index1] >> 8) & 0xff;
tb1 = input[index1] & 0xff;

tr2 = (input[index2] >> 16) & 0xff;
tg2 = (input[index2] >> 8) & 0xff;
tb2 = input[index2] & 0xff;

int tr = (int)(tr1 * (1-u) + tr2 * u);
int tg = (int)(tg1 * (1-u) + tg2 * u);
int tb = (int)(tb1 * (1-u) + tb2 * u);

return new int[]{tr, tg, tb};
}

package com.gloomyfish.filter.study;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;

public class ShearFilter extends AbstractBufferedImageOp {
private int outw;
private int outh;
private double angle;
private Color backgroundColor;
private boolean vertical;

public void setVertical(boolean vertical) {
this.vertical = vertical;
}

public ShearFilter()
{
backgroundColor = Color.BLACK;
vertical = false;
this.angle = 20;
}

public int getOutw() {
return outw;
}
public void setOutw(int outw) {
this.outw = outw;
}
public int getOuth() {
return outh;
}
public void setOuth(int outh) {
this.outh = outh;
}
public double getAngle() {
return angle;
}
public void setAngle(double angle) {
this.angle = angle;
}
public Color getBackgroundColor() {
return backgroundColor;
}
public void setBackgroundColor(Color backgroundColor) {
this.backgroundColor = backgroundColor;
}
@Override
public BufferedImage filter(BufferedImage src, BufferedImage dest) {
int width = src.getWidth();
int height = src.getHeight();

double angleValue = (angle/180.0d) * Math.PI;
outh = vertical ? (int)(height + width * Math.tan(angleValue)) : height;
outw = vertical ? width : (int)(width + height * Math.tan(angleValue));
System.out.println("after shear, new width : " + outw);
System.out.println("after shear, new height: " + outh);

int[] inPixels = new int[width*height];
int[] outPixels = new int[outh*outw];
getRGB( src, 0, 0, width, height, inPixels );
int index = 0;
for(int row=0; row<outh; row++) {
int ta = 0;
for(int col=0; col<outw; col++) {
double prow = vertical ? row + Math.tan(angleValue) * (col - width) : row;
double pcol = vertical ?

col : col + Math.tan(angleValue) * (row - height); int[] rgb = getPixel(inPixels, width, height, prow, pcol); index = row * outw + col; outPixels[index] = (ta << 24) | (rgb[0] << 16) | (rgb[1] << 8) | rgb[2]; } } if ( dest == null ) dest = createCompatibleDestImage( src, null ); setRGB( dest, 0, 0, outw, outh, outPixels ); return dest; } private int[] getPixel(int[] input, int width, int height, double prow, double pcol) { double row = Math.floor(prow); double col = Math.floor(pcol); if(row < 0 || row >= height) { return new int[]{backgroundColor.getRed(), backgroundColor.getGreen(), backgroundColor.getBlue()}; } if(col < 0 || col >= width) { return new int[]{backgroundColor.getRed(), backgroundColor.getGreen(), backgroundColor.getBlue()}; } double u = vertical ? (prow - row) : pcol - col; int nextCol = (int)(col + 1); int nextRow = (int)(row + 1); if((col + 1) >= width) { nextCol = (int)col; } if((row + 1) >= height) { nextRow = (int)row; } int index1 = (int)(row * width + col); int index2 = vertical ? (int)(nextRow * width + col) : (int)(row * width + nextCol); int tr1, tr2; int tg1, tg2; int tb1, tb2; tr1 = (input[index1] >> 16) & 0xff; tg1 = (input[index1] >> 8) & 0xff; tb1 = input[index1] & 0xff; tr2 = (input[index2] >> 16) & 0xff; tg2 = (input[index2] >> 8) & 0xff; tb2 = input[index2] & 0xff; int tr = (int)(tr1 * (1-u) + tr2 * u); int tg = (int)(tg1 * (1-u) + tg2 * u); int tb = (int)(tb1 * (1-u) + tb2 * u); return new int[]{tr, tg, tb}; } public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) { if ( dstCM == null ) dstCM = src.getColorModel(); return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(outw, outh), dstCM.isAlphaPremultiplied(), null); } }

## opencv 数字图像处理-图像错切

2015-06-28 21:29:22 u012005313 阅读数 3521
• ###### Darknet安装与测试

从理论到实践，快速入门Spring Boot 2.x 从Spring Boot扩展到Spring相关知识的学习和实战 Spring Boot与其他技术框架的集成 Spring Boot部分功能源码解析

23742课时 0分钟 1015人学习 马孔伟
免费试看

####################################################

void imageTwist(IplImage *src, IplImage *res, float ratio)
{
cvZero(res);
int res_wid;
int res_hei;

unsigned char* src_data = (unsigned char*)src->imageData;
unsigned char* res_data = (unsigned char*)res->imageData;

for (int i=0; i<src->height; i++)
{
if (ratio >= 0)
for (int j=0; j<src->width; j++)
{
res_hei=i;
res_wid=j+res_hei*ratio;
res_data[res_hei*res->widthStep+res_wid] = src_data[i*src->widthStep+j];
}
else
{
int offset=ratio*src->height;
for (int j=src->width-1; j>=0; j--)
{
res_hei=i;
res_wid=j+res_hei*ratio;
res_data[res_hei*res->widthStep+res_wid+offset] = src_data[i*src->widthStep+j];
}
}
}

cvNamedWindow("src");
cvNamedWindow("res");
cvShowImage("src", src);
cvShowImage("res", res);
cvWaitKey(0);
cvReleaseImage(&src);
cvReleaseImage(&res);
cvDestroyAllWindows();
}

void imageCutting(void)
{
if (src == NULL)
exit(0);

float ratio;
cout<<"输入水平错切比率："<<endl;
cin>>ratio;

int res_wid;
int res_hei;
if (ratio < 0)
{
res_wid=src->width+src->height*ratio*(-1);
} else {
res_wid=src->width+src->height*ratio;
}

res_hei=src->height;
CvSize size=cvSize(res_wid, res_hei);
res=cvCreateImage(size, src->depth, src->nChannels);
if (res == NULL)
exit(0);

imageTwist(src, res, ratio);//图像扭曲
}

#########################################################

void imageTwistV(IplImage *src, IplImage *res, float ratio)
{
cvZero(res);
int res_wid;
int res_hei;

unsigned char* src_data = (unsigned char*)src->imageData;
unsigned char* res_data = (unsigned char*)res->imageData;

for (int i=0; i<src->width; i++)
{
if (ratio >= 0)
{
int offset=ratio*src->width;
for (int j=0; j<src->height; j++)
{
res_wid=i;
res_hei=j+offset-res_wid*ratio;
res_data[res_hei*res->widthStep+res_wid] = src_data[j*src->widthStep+i];
}
}
else
{
//int offset=ratio*src->height*(-1);
for (int j=src->height-1; j>=0; j--)
{
res_wid=i;
res_hei=j+res_wid*ratio*(-1);
res_data[res_hei*res->widthStep+res_wid] = src_data[j*src->widthStep+i];
}
}
}

cvNamedWindow("src");
cvNamedWindow("res");
cvShowImage("src", src);
cvShowImage("res", res);
cvWaitKey(0);
cvReleaseImage(&src);
cvReleaseImage(&res);
cvDestroyAllWindows();
}

void imageCutting(void)
{
if (src == NULL)
exit(0);

float ratio=0;
cout<<"输入垂直错切比率："<<endl;
cin>>ratio;

int res_wid;
int res_hei;
if (ratio < 0)
{
res_hei=src->height+src->width*ratio*(-1);
//res_wid=src->width+src->height*ratio*(-1);
} else {
res_hei=src->height+src->width*ratio;
//res_wid=src->width+src->height*ratio;
}

res_wid=src->width;
//res_hei=src->height;
CvSize size=cvSize(res_wid, res_hei);
res=cvCreateImage(size, src->depth, src->nChannels);
if (res == NULL)
exit(0);

//	imageTwistH(src, res, ratio);//图像扭曲
imageTwistV(src, res, ratio);
}

## MATLAB中图像的几何操作

2012-04-18 12:15:55 caiqi1123 阅读数 11450
• ###### Darknet安装与测试

从理论到实践，快速入门Spring Boot 2.x 从Spring Boot扩展到Spring相关知识的学习和实战 Spring Boot与其他技术框架的集成 Spring Boot部分功能源码解析

23742课时 0分钟 1015人学习 马孔伟
免费试看
 1.1图像的裁剪： 在实际应用或科研领域，很多时候要对图像裁剪操作。图像裁剪就是在源图像或者大图像中裁剪图像块来，这个图像块一般是多边形的。图像裁剪是图像处理中最基本的操作之一。 使用imcrop函数对图像进行裁剪操作，然后制作出动画效果，该函数有两个参数，一个用来指定裁剪的图像，另一个用来指定裁剪矩形。一般格式如下：            imcrop（A，[80,120,100,50]）; [80,120,100,50]的含义是：以图像的（80，,10）点位裁剪矩形的左上角坐标，裁剪的宽度是100，高度是50。 用roipoly函数进行多边形区域的裁剪，              roipoly（A，c1，c2）;c1，c2定义区域的向量。 1.2图像的缩放： 在图像缩放过程中，涉及图像数据的删除与增加。特别是图像放大的时候需要考虑如何自傲扩大后的空隙中加入新的图像颜色数据。增加颜色数据的方法主要根据周围相近像素的颜色值进行插值计算。 使用imresize函数缩放图像.形式为：imreseze（A，n）A为图像，n为放大倍数。 另外一种是：imreseze（A，[n,m]）把原有的图像放大为行列分别为n,m的图像。 三种插值方法： 1.最近邻插值法：是imreseze默认的方法， 2.双线性插值方法：格式：imreseze（A，n，'bilinear'）. 3.双立方插值方法：格式：imreseze（A，n，'bicubic'）. 1.3图像的选转: 使用imrotate函数进行图像的旋转。 一般的格式为：imrotate（A，Angle,Method,Bbox）. Angle：旋转地角度，Method：为插值的方法，可以在，nearest、bilinear、bicubic中选着，Bbox为loose是底板放大，显示整个图形，导致图形变小是默认的情况，为crop时旋转图形的底板不变图形可能被切割，一般使用crop形式。 2.1图像的几何变换 图像二维仿射变换MATLAB使用imtransform函数完成图像空间变换。 格式imtransform（A,T）。 其中参数A是要变换的图像，T是由makeform函数产生的变换结构. 在maketform('P',......)函数中，参数P可以议一下 形式： affine：仿射变换形式。 projective:投影变换形式； cusyom：自定义函数变换； box：利用函数中的另外参数产生仿射变换结构； composite：该参数是实现多次调用tformfwd功能； maketform：函数就是利用给定的参数建立变换结构，然后把该变换结构赋予结构变量T。根据得到的结构体变量T，调用imtransform（A,T）函数进行变换。 3:图像的领域操作 领域操作指在图像处理时，处理像素的某领域内各个像素值，输出要处理的像素的新值。领域财政是图像处理（例如图像增强、图像滤波等）时经常用到的操作方法。使用该方法处理图像时一般使用算子模板进行再图像上滑动，划定的时候对模板进过区域进行运算，把计算的结果作为区域中心像素的新值，所以有时领域操作也称为划定领域操作。领域操作方法充分地领用了图像相领像素间的颜色关系，利用相邻像素间的颜色分布对图像进行平滑、增强、边缘提取、滤波、恢复等操作。

(x,y) = T{(w,z)} = (w/2, z/2)

（1）上图Scaling中，如果A图宽高位(w1,h1)。现在要求将A图缩放为宽高为(w2,h2)的B图。那如何分别求宽高的缩放率呢？其实可以根据Scaling中的公式。既然知道A和B图的宽高，即知道了图像右下角的坐标(w1,h1)和(w2,h2).所以sx=w2/w1;sy=h2/h1。

（2）

wz = [3 4 1];
T = [2 0 0; 0 3 0; 0 0 1];
xy = wz * T;
wz = xy * inv(T);

T = [2 0 0; 0 3 0; 0 0 1];
tform = maketform('affine', T);
wz = [1 2; 3 4];
xy = tformfwd(wz, tform);
wz = tforminv(xy, tform);

g = imresize(f, scale);
g = imresize(f, [ROW COL]);

g = imrotate(f, angle);

g = imcrop(f, [X, Y, WIDTH, HEIGHT]);

g = imtransform(f, tform, interp);

f = chekerboard(50);
s = 0.8;
theta = pi/6;
T = [s*cos(theta) s*sin(theta) 0;
-s*sin(theta) s*cos(theta) 0;
0 0 1];
tform = maketform('affine', T);
g = imtransform(f, tform);

AffineTransform类描述了一种二维仿射变换的功能，它是一种二维坐标到二维坐标之间的线性变换，保持二维图形的平直性（译注： straightness，即变换后直线还是直线不会打弯，圆弧还是圆弧）和平行性（译注：parallelness，其实是指保二维图形间的相对位置关系不变，平行线还是平行线，而直线上点的位置顺序不变，另特别注意向量间夹角可能会发生变化。）仿射变换可以通过一系列的原子变换的复合来实现，包括：平移Translation）、缩放Scale）、翻转Flip）、旋转Rotation）和错切Shear）。

PerspectiveTransform是描述一种实际三维空间到二维空间的变换。始终遵循“近大远小”的规律。当相机的光轴垂直于物体表面时{因为物体的表面点z坐标都相等，故没有“近大远小”的现象。}，发生的是类似于某些仿射变换，如平移Translation）、缩放Scale）、翻转Flip）、旋转Rotation）【没有“错切”！】；当相机的光轴不垂直于物体表面时，发生的是透视变换。

## 数字图像处理Python语言实现-图像几何变换-错切变换

2019-07-16 12:58:26 wujuxKkoolerter 阅读数 0
• ###### Darknet安装与测试

从理论到实践，快速入门Spring Boot 2.x 从Spring Boot扩展到Spring相关知识的学习和实战 Spring Boot与其他技术框架的集成 Spring Boot部分功能源码解析

23742课时 0分钟 1015人学习 马孔伟
免费试看

# 图像几何变换-错切变换

## 1 水平错切变换

$\begin{cases} x' = x + by \\ y' = y \end{cases} \tag{8-1}$

## 2 垂直方向错切变换

$\begin{cases} x' = x \\ y' = y + dx \end{cases} \tag{8-2}$

## DAY13 Matlab实现图像错切源代码

2016-07-05 19:15:00 a18861227 阅读数 342
• ###### Darknet安装与测试

从理论到实践，快速入门Spring Boot 2.x 从Spring Boot扩展到Spring相关知识的学习和实战 Spring Boot与其他技术框架的集成 Spring Boot部分功能源码解析

23742课时 0分钟 1015人学习 马孔伟
免费试看
Matlab实现图像错切源代码

%错切
im1=rgb2gray(im);
figure,imshow(im1);
[row,col]=size(im1); %获取行数 和 列数

%图像的水平错切
G=zeros(row,col);
a=pi/6; %水平错切30度
b=tan(a);
for m=1:row
for n=1:col
G(round(m+b*n),n)=im1(m,n);
end
end
figure,imshow(uint8(G));

%图像的垂直错切
G=zeros(row,col);
a=pi/6; %水平错切30度
b=tan(a);
for m=1:row
for n=1:col
G(n,round(m+b*n))=im1(m,n);
end
end
figure,imshow(uint8(G));