python详细图像仿射变换讲解
仿射变换简介
什么是放射变换
图像上的仿射变换, 其实就是图片中的一个像素点,通过某种变换,移动到另外一个地方。
从数学上来讲, 就是一个向量空间进行一次线形变换并加上平移向量, 从而变换到另外一个向量空间的过程。
向量空间m : m=(x,y)
向量空间n : n=(x′,y′)
向量空间从m到n的变换 n=A∗m+b
整理得到:
将A跟b 组合在一起就组成了仿射矩阵 M。 它的维度是2∗3
使用不同的矩阵M,就获得了不同的2D仿射变换效果。
在opencv中,实现2D仿射变换, 需要借助warpAffine
函数。
cv2.warpAffine(image, M, (image.shape[1], image.shape[0])
复制代码
接下来,带你结合具体的2D仿射变换,分析其变换矩阵。
图像平移
公式推导
平移可以说是最简单的一种空间变换。其表达式为:
其中(b0,b1) 是偏移量。
例程
如果是向右平移10个像素, 向下平移30个像素的话, 那么变换矩阵M可以为:
演示代码
向右平移10个像素, 向下平移30个像素:
import cv2
import numpy as np
img = cv2.imread('lena1.jpg')
height,width,channel = img.shape
# 声明变换矩阵 向右平移10个像素, 向下平移30个像素
M = np.float32([[1, 0, 10], [0, 1, 30]])
# 进行2D 仿射变换
shifted = cv2.warpAffine(img, M, (width, height))
cv2.imwrite('shift_right_10_down_30.jpg', shifted)
复制代码
原始图像:
向右平移10个像素, 向下平移30个像素图像:
向左平移10个像素, 向上平移30个像素:
# 声明变换矩阵 向左平移10个像素, 向上平移30个像素
M = np.float32([[1, 0, -10], [0, 1, -30]])
# 进行2D 仿射变换
shifted = cv2.warpAffine(img, M, (width, height))
cv2.imwrite('shift_right_-10_down_-30.jpg', shifted)
复制代码
仿射变换图像:
图像平移v2
我们可以用translate
这个函数把这个操作封装一下:
def translate(image, x, y):
M = np.float32([[1, 0, x], [0, 1, y]])
shifted = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))
return shifted
复制代码
完成一些的代码:
import cv2
import numpy as np
img = cv2.imread('cat.png')
def translate(image, x, y):
M = np.float32([[1, 0, x], [0, 1, y]])
shifted = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))
return shifted
shifted = translate(img, 10, 30)
cv2.imwrite('shift_right_10_down_30.png', shifted)
复制代码
处理结果同上。。。
图像旋转
利用getRotationMatrix2D实现旋转
opencv中getRotationMatrix2D
函数可以直接帮我们生成M
而不需要我们在程序里计算三角函数:
getRotationMatrix2D(center, angle, scale)
复制代码
参数解析
center
旋转中心点(cx, cy)
你可以随意指定angle
旋转的角度 单位是角度 逆时针方向为正方向 , 角度为正值代表逆时针scale
缩放倍数. 值等于1.0
代表尺寸不变
该函数返回的就是仿射变换矩阵M
示例代码
import cv2
import numpy as np
# 获取旋转矩阵
rotateMatrix = cv2.getRotationMatrix2D((100, 200), 90, 1.0)
#设置numpy矩阵的打印格式
np.set_printoptions(precision=2,suppress=True)
print(rotateMatrix)
OUTPUT
[[ 0\. 1\. -100.]
[ -1\. 0\. 300.]]
复制代码
为了使用方便, 你也可以封装一下旋转过程
def rotate(image, angle, center = None, scale = 1.0):
(h, w) = image.shape[:2]
if center is None:
center = (w / 2, h / 2)
M = cv2.getRotationMatrix2D(center, angle, scale)
rotated = cv2.warpAffine(image, M, (w, h))
return rotated
复制代码
演示代码
# -*- coding: utf-8 -*-
'''
围绕原点处旋转 (图片左上角) 正方向为逆时针
利用getRotationMatrix2D函数生成仿射矩阵
'''
import numpy as np
import cv2
from math import cos,sin,radians
from matplotlib import pyplot as plt
img = cv2.imread('lena1.jpg')
height, width, channel = img.shape
# 求得图片中心点, 作为旋转的轴心
cx = int(width / 2)
cy = int(height / 2)
# 旋转的中心
center = (cx, cy)
new_dim = (width, height)
# 进行2D 仿射变换
# 围绕原点 逆时针旋转30度
M = cv2.getRotationMatrix2D(center=center,angle=30, scale=1.0)
rotated_30 = cv2.warpAffine(img, M, new_dim)
# 围绕原点 逆时针旋转30度
M = cv2.getRotationMatrix2D(center=center,angle=45, scale=1.0)
rotated_45 = cv2.warpAffine(img, M, new_dim)
# 围绕原点 逆时针旋转30度
M = cv2.getRotationMatrix2D(center=center,angle=60, scale=1.0)
rotated_60 = cv2.warpAffine(img, M, new_dim)
plt.subplot(221)
plt.title("Src Image")
plt.imshow(img[:,:,::-1])
plt.subplot(222)
plt.title("Rotated 30 Degree")
plt.imshow(rotated_30[:,:,::-1])
plt.subplot(223)
plt.title("Rotated 45 Degree")
plt.imshow(rotated_45[:,:,::-1])
plt.subplot(224)
plt.title("Rotated 60 Degree")
plt.imshow(rotated_60[:,:,::-1])
plt.show()
复制代码
原始图形:
图像旋转图像(逆时针30度、45度、60度):
利用wrapAffine实现缩放
数学原理推导
围绕原点进行旋转
由此我们得出
所以对应的变换矩阵为
注意,这里我们进行公式推导的时候,参照的原点是在左下角, 而在OpenCV中图像的原点在图像的左上角, 所以我们在代码里面对theta取反。
我们可以利用math
包中的三角函数。但是有一点需要注意 :三角函数输入的角度是弧度制而不是角度制。
我们需要使用radians(x)
函数, 将角度转变为弧度。
import math
math.radians(180)
3.141592653589793
复制代码
代码演示
# -*- coding: utf-8 -*-
'''
围绕原点处旋转 (图片左上角) 正方向为逆时针
'''
import numpy as np
import cv2
import math
from matplotlib import pyplot as plt
img = cv2.imread('lena1.jpg')
height, width, channel = img.shape
def getRotationMatrix2D(theta):
# 角度值转换为弧度值
# 因为图像的左上角是原点 需要×-1
theta = math.radians(-1*theta)
M = np.float32([
[math.cos(theta), -math.sin(theta), 0],
[math.sin(theta), math.cos(theta), 0]])
return M
# 进行2D 仿射变换
# 围绕原点 顺时针旋转30度
M = getRotationMatrix2D(30)
rotated_30 = cv2.warpAffine(img, M, (width, height))
# 围绕原点 顺时针旋转45度
M = getRotationMatrix2D(45)
rotated_45 = cv2.warpAffine(img, M, (width, height))
# 围绕原点 顺时针旋转60度
M = getRotationMatrix2D(60)
rotated_60 = cv2.warpAffine(img, M, (width, height))
plt.subplot(221)
plt.title("Src Image")
plt.imshow(img[:,:,::-1])
plt.subplot(222)
plt.title("Rotated 30 Degree")
plt.imshow(rotated_30[:,:,::-1])
plt.subplot(223)
plt.title("Rotated 45 Degree")
plt.imshow(rotated_45[:,:,::-1])
plt.subplot(224)
plt.title("Rotated 60 Degree")
plt.imshow(rotated_60[:,:,::-1])
plt.show()
复制代码
原始图像:
旋转之后演示图:
围绕任意点进行旋转
数学原理推导
那么如何围绕任意点进行旋转呢?
可以先把当前的旋转中心点平移到原点处, 在原点处旋转后再平移回去。
假定旋转中心为 (cx,cy)
其中
所以
代码演示
# -*- coding: utf-8 -*-
'''
围绕画面中的任意一点旋转
'''
import numpy as np
import cv2
from math import cos,sin,radians
from matplotlib import pyplot as plt
img = cv2.imread('lena1.jpg')
height, width, channel = img.shape
theta = 45
def getRotationMatrix2D(theta, cx=0, cy=0):
# 角度值转换为弧度值
# 因为图像的左上角是原点 需要×-1
theta = radians(-1 * theta)
M = np.float32([
[cos(theta), -sin(theta), (1-cos(theta))*cx + sin(theta)*cy],
[sin(theta), cos(theta), -sin(theta)*cx + (1-cos(theta))*cy]])
return M
# 求得图片中心点, 作为旋转的轴心
cx = int(width / 2)
cy = int(height / 2)
# 进行2D 仿射变换
# 围绕原点 逆时针旋转30度
M = getRotationMatrix2D(30, cx=cx, cy=cy)
rotated_30 = cv2.warpAffine(img, M, (width, height))
# 围绕原点 逆时针旋转45度
M = getRotationMatrix2D(45, cx=cx, cy=cy)
rotated_45 = cv2.warpAffine(img, M, (width, height))
# 围绕原点 逆时针旋转60度
M = getRotationMatrix2D(60, cx=cx, cy=cy)
rotated_60 = cv2.warpAffine(img, M, (width, height))
plt.subplot(221)
plt.title("Src Image")
plt.imshow(img[:,:,::-1])
plt.subplot(222)
plt.title("Rotated 30 Degree")
plt.imshow(rotated_30[:,:,::-1])
plt.subplot(223)
plt.title("Rotated 45 Degree")
plt.imshow(rotated_45[:,:,::-1])
plt.subplot(224)
plt.title("Rotated 60 Degree")
plt.imshow(rotated_60[:,:,::-1])
plt.show()
复制代码
旋转效果:
围绕图片中心点旋转30度至60度
图像缩放
利用resize函数实现缩放
opencv其实有专门进行图像缩放的函数resize
。
resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) -> dst
复制代码
参数解析
src
输入图片dsize
输出图片的尺寸dst
输出图片fx
x轴的缩放因子fy
y轴的缩放因子interpolation
插值方式INTER_NEAREST
- 最近邻插值INTER_LINEAR
- 线性插值(默认)INTER_AREA
- 区域插值INTER_CUBIC
- 三次样条插值INTER_LANCZOS4
- Lanczos插值
在使用的时候, 我们可以传入指定的图片的尺寸dsize
'''
使用resize函数对图像进行缩放
'''
import cv2
import numpy as np
img = cv2.imread('lena1.jpg')
height,width,channel = img.shape
# 声明新的维度
new_dimension = (400, 400)
# 指定新图片的维度与插值算法(interpolation)
resized = cv2.resize(img, new_dimension)
cv2.imwrite('lena_resize_400_400.png', resized)
复制代码
原始图像:
缩放后的图像:
或者指定缩放因子fx,fy
将dsize
设置为 None
, 然后指定fx fy
import cv2
import numpy as np
img = cv2.imread('lena1.jpg')
height,width,channel = img.shape
# 指定新图片的维度与插值算法(interpolation)
resized = cv2.resize(img, None, fx=1.5, fy=2)
cv2.imwrite('lena_resize_fx_fy.jpg', resized)
复制代码
运行结果如下:
或者指定输出图片,并传入输出图片的size:
'''
根据fx跟fy进行图像缩放
'''
import cv2
import numpy as np
img = cv2.imread('lena1.jpg')
height,width,channel = img.shape
# 指定输出图片
dst = np.zeros((100, 100, 3), dtype='uint8')
# 指定新图片的维度与插值算法(interpolation)
cv2.resize(img, dst=dst, dsize=(dst.shape[1], dst.shape[0]), fx=1.5, fy=2)
cv2.imwrite('lena_resize_from_dst.jpg', dst)
复制代码
运行结果如下:
更详细的使用说明见opencv-resize 文档
为了方便使用, 我们也可以将其封装成函数
def resize(image, width = None, height = None, inter = cv2.INTER_AREA):
dim = None
(h, w) = image.shape[:2]
if width is None and height is None:
return image
if width is None:
r = height / float(h)
dim = (int(w * r), height)
if height is None:
r = width / float(w)
dim = (width, int(h * r))
if width and height:
dim = (width, height)
resized = cv2.resize(image, dim, interpolation = inter)
return resized
复制代码
分辨率 从 5 5 放大到 1000 1000, 选择不同的插值算法,对应的演示效果:
'''
差值算法对比
'''
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = np.uint8(np.random.randint(0,255,size=(5,5)))
height,width= img.shape
# 声明新的维度
new_dimension = (1000, 1000)
plt.subplot(231)
plt.title("SRC Image")
plt.imshow(img,cmap='seismic')
plt.subplot(232)
resized = cv2.resize(img, new_dimension, interpolation = cv2.INTER_NEAREST)
plt.title("INTER_NEAREST")
plt.imshow(resized,cmap='seismic')
plt.subplot(233)
resized = cv2.resize(img, new_dimension, interpolation = cv2.INTER_LINEAR)
plt.title("INTER_LINEAR")
plt.imshow(resized,cmap='seismic')
plt.subplot(234)
resized = cv2.resize(img, new_dimension, interpolation = cv2.INTER_AREA)
plt.title("INTER_AREA")
plt.imshow(resized,cmap='seismic')
plt.subplot(235)
resized = cv2.resize(img, new_dimension, interpolation = cv2.INTER_CUBIC)
plt.title("INTER_CUBIC")
plt.imshow(resized,cmap='seismic')
plt.subplot(236)
resized = cv2.resize(img, new_dimension, interpolation = cv2.INTER_LANCZOS4)
plt.title("INTER_LANCZOS4")
plt.imshow(resized,cmap='seismic')
plt.show()
复制代码
利用wrapAffine实现缩放
数学原理
对图像的伸缩变换的变换矩阵M为
其中,
fx
:代表x轴的焦距(缩放因子)
fy
:代表y轴的焦距(缩放因子)
则可以得出以下式子:
具体代码演示
源代码:
'''
使用仿射矩阵实现
'''
import numpy as np
import cv2
img = cv2.imread('lena1.jpg')
height,width,channel = img.shape
# x轴焦距 1.5倍
fx = 1.5
# y轴焦距 2倍
fy = 2
# 声明变换矩阵 向右平移10个像素, 向下平移30个像素
M = np.float32([[fx, 0, 0], [0, fy, 0]])
# 进行2D 仿射变换
resized = cv2.warpAffine(img, M, (int(width*fx), int(height*fy)))
cv2.imwrite('resize_raw.jpg', resized)
复制代码
运行效果:
原始图像:
我们利用random 模块生成一个5×5的随机矩阵。
# 生成一个随机噪点
img = np.uint8(np.random.randint(0,255,size=(5,5)))
复制代码
源代码:
'''
仿射矩阵实现缩放 fx,fy
'''
import numpy as np
import cv2
from matplotlib import pyplot as plt
# 生成一个随机噪点
img = np.uint8(np.random.randint(0,255,size=(5,5)))
height,width = img.shape
# x轴焦距 1.5倍
fx = 1.5
# y轴焦距 2倍
fy = 2
# 声明变换矩阵 向右平移10个像素, 向下平移30个像素
M = np.float32([[fx, 0, 0], [0, fy, 0]])
# 进行2D 仿射变换
resized = cv2.warpAffine(img, M, (int(width*fx), int(height*fy)))
print(img)
print(resized)
# 数据可视化
plt.subplot(121)
plt.imshow(img, cmap="gray")
plt.subplot(122)
plt.imshow(resized,cmap="gray")
plt.show()
复制代码
原图:
[[224 25 25 165 16]
[ 37 170 114 16 101]
[181 5 7 94 41]
[206 167 23 133 115]
[217 115 154 97 65]]
复制代码
缩放后:
[[224 93 25 25 117 114 16]
[131 109 88 70 83 80 59]
[ 37 124 151 114 50 45 101]
[109 95 78 61 57 61 71]
[181 66 6 7 64 76 41]
[194 123 62 15 80 101 78]
[206 180 118 23 95 127 115]
[212 165 123 89 106 106 90]
[217 150 128 154 117 86 65]
[109 75 64 77 58 43 33]]
复制代码
为了更加直观的感受, 我们可以进行数据可视化。
我们使用matplotlib
进行绘制 resize前与resize之后的图片。
图像翻转
使用flip函数实现翻转
flip 函数原型
flip(src, flipCode[, dst]) -> dst
复制代码
参数解析
src
输入图片flipCode
翻转代码1
水平翻转 Horizontally (图片第二维度是column)0
垂直翻转 Vertically (图片第一维是row)-1
同时水平翻转与垂直反转 Horizontally & Vertically
为了方便使用, 你也可以封装成下面的函数
def flip(image, direction):
if direction == "h":
flipped = cv2.flip(image, 1)
elif direction == "v":
flipped = cv2.flip(image, 0)
else:
# both horizontally and vertically
flipped = cv2.flip(image, -1)
复制代码
具体源码及效果展示
'''
反转Demo
'''
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('lena1.jpg')
def bgr2rbg(img):
'''
将颜色空间从BGR转换为RBG
'''
return img[:,:,::-1]
# 水平翻转
flip_h = cv2.flip(img, 1)
# 垂直翻转
flip_v = cv2.flip(img, 0)
# 同时水平翻转与垂直翻转
flip_hv = cv2.flip(img, -1)
plt.subplot(221)
plt.title('SRC')
plt.imshow(bgr2rbg(img))
plt.subplot(222)
plt.title('Horizontally')
plt.imshow(bgr2rbg(flip_h))
plt.subplot(223)
plt.title('Vertically')
plt.imshow(bgr2rbg(flip_v))
plt.subplot(224)
plt.title('Horizontally & Vertically')
plt.imshow(bgr2rbg(flip_hv))
plt.show()
复制代码
利用numpy的索引实现翻转
利用numpy
中ndarray
的索引, 我们可以非常方便地实现图像翻转。
# 水平翻转
flip_h = img[:,::-1]
# 垂直翻转
flip_v = img[::-1]
# 水平垂直同时翻转
flip_hv = img[::-1, ::-1]
复制代码
具体源码及效果展示
'''
使用numpy的索引进行图像反转
'''
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('lena1.jpg')
height,width,channel = img.shape
# 水平翻转
flip_h = img[:,::-1]
# 垂直翻转
flip_v = img[::-1]
# 水平垂直同时翻转
flip_hv = img[::-1, ::-1]
def bgr2rbg(img):
'''
将颜色空间从BGR转换为RBG
'''
return img[:,:,::-1]
plt.subplot(221)
plt.title('SRC')
plt.imshow(bgr2rbg(img))
plt.subplot(222)
plt.title('Horizontally')
plt.imshow(bgr2rbg(flip_h))
plt.subplot(223)
plt.title('Vertically')
plt.imshow(bgr2rbg(flip_v))
plt.subplot(224)
plt.title('Horizontally & Vertically')
plt.imshow(bgr2rbg(flip_hv))
plt.show()
12345678910111213141516171819202122232425262728293031323334353637383940414243
复制代码
利用wrapAffine实现翻转
图像翻转的数学原理
注:
width
代表图像的宽度;height
代表图像的高度
水平翻转的变换矩阵
垂直翻转的变换矩阵
同时进行水平翻转与垂直翻转
具体源码及效果展示
'''
使用仿射矩阵实现反转
'''
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('lena1.jpg')
height,width,channel = img.shape
# 水平翻转
M1 = np.float32([[-1, 0, width], [0, 1, 0]])
flip_h = cv2.warpAffine(img, M1, (width, height))
# 垂直翻转
M2 = np.float32([[1, 0, 0], [0, -1, height]])
flip_v = cv2.warpAffine(img, M2, (width, height))
# 水平垂直同时翻转
M3 = np.float32([[-1, 0, width], [0, -1, height]])
flip_hv = cv2.warpAffine(img, M3, (width, height))
def bgr2rbg(img):
'''
将颜色空间从BGR转换为RBG
'''
return img[:,:,::-1]
plt.subplot(221)
plt.title('SRC')
plt.imshow(bgr2rbg(img))
plt.subplot(222)
plt.title('Horizontally')
plt.imshow(bgr2rbg(flip_h))
plt.subplot(223)
plt.title('Vertically')
plt.imshow(bgr2rbg(flip_v))
plt.subplot(224)
plt.title('Horizontally & Vertically')
plt.imshow(bgr2rbg(flip_hv))
plt.show()
复制代码
python详细图像仿射变换讲解的更多相关文章
- Python 调用图像融合API
Python 调用图像融合API 本文记录使用Python,调用腾讯AI开放平台的图像融合API.官网给出的Demo用的是PHP,博主作为Python的粉丝,自然想用它来和『最好的』的语言一较高下,顺 ...
- Python实现图像直方图均衡化算法
title: "Python实现图像直方图均衡化算法" date: 2018-06-12T17:10:48+08:00 tags: [""] categorie ...
- Python实现图像边缘检测算法
title: "Python实现图像边缘检测算法" date: 2018-06-12T17:06:53+08:00 tags: ["图形学"] categori ...
- Python: scikit-image 图像的基本操作
这个用例说明Python 的图像基本运算 import numpy as np from skimage import data import matplotlib.pyplot as plt cam ...
- Python中图像的缩放 resize()函数的应用
cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) -> dst 参数说明: src - 原图 dst - 目标图像.当参数ds ...
- python 在图像上写中文字体 (python write Chinese in image)
本人处理图像的时候经常使用opencv的包,但是 cv2.putText 显示不了中文,所以查找了如何在python在图像上写中文的方法,在伟大的Stack Overflow上面找到一个方法,分享给大 ...
- python 处理图像出现The lower bounary is neither an array of the same size and same type as src, nor a scalar in function inRange
在用python处理图像过程中出现如下错误 导致这个错误的原因是im是二维,而lower_green和upper_green是三维,所以无法用inRange处理. 由上图可以看出image本来是具有高 ...
- python 修改图像大小和分辨率
1 概念: 分辨率,指的是图像或者显示屏在长和宽上各拥有的像素个数.比如一张照片分辨率为1920x1080,意思是这张照片是由横向1920个像素点和纵向1080个像素点构成,一共包含了1920x108 ...
- python处理图像矩阵--值转为int
1. 在用python处理图像数字矩阵时,若对矩阵进行了加减乘除等运算,可能会造成矩阵元素值溢出,然后某些元素值可能都被赋为255:之后若重新显示图像,可能会没有什么变化,此时,可以将运算后的矩阵值转 ...
随机推荐
- C# 读取路径的各种方式
//1.获取模块的完整路径. string path1 = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; // ...
- 万万没想到!ModelArts与AppCube组CP了
摘要:嘘,华为云内部都不知道的秘密玩法,我悄悄告诉您! 双"魔"合璧庆双节 ↑开局一张图,故事全靠编 华为云的一站式开发平台ModelArts和应用魔方AppCube居然能玩到一起 ...
- 达梦产品技术支持培训-day6-DM性能诊断与优化
(本文只作为个人随笔用途,非官方文档,请勿作他用,谢谢) 1.DM8查询优化基本思路 1.1 操作系统性能诊断 linux常用系统监控命令 使用 top 命令查看cpu使用率 使用 iostat 命令 ...
- [HAOI 2017]八纵八横
线段树分治+线形基. 线段树分治是个锤子?? 以时间轴构建线段树,把每个环以"对线段树产生影响的时间区间"的形式加入线段树即可. #include<bits/stdc++.h ...
- SQL学习 小知识点(一)
这是我在做实验的时候总结的,随着学习可能会做更多的小总结 ssms上面把所有代码写下来后一块执行是行不通的(极大可能会报错),推测可能是因为ssms先对代码的语法进行了检查. --My expe ...
- 营口6378.7939(薇)xiaojie:营口哪里有xiaomei
营口哪里有小姐服务大保健[微信:6378.7939倩儿小妹[营口叫小姐服务√o服务微信:6378.7939倩儿小妹[营口叫小姐服务][十微信:6378.7939倩儿小妹][营口叫小姐包夜服务][十微信 ...
- 机器学习:集成学习:随机森林.GBDT
集成学习(Ensemble Learning) 集成学习的思想是将若干个学习器(分类器&回归器)组合之后产生一个新学习器.弱分类器(weak learner)指那些分类准确率只稍微好于随机猜测 ...
- 快速解读linq语法
在说LINQ之前必须先说说几个重要的C#语言特性 一:与LINQ有关的语言特性 1.隐式类型 (1)源起 在隐式类型出现之前, 我们在声明一个变量的时候, 总是要为一个变量指定他的类型 甚至在fore ...
- java axis调用带有soap头(soapheader)的.net webservice
使用axis调用.net带soapheader的webservice是如何实现的,现在贴出代码 <?xml version="1.0" encoding="utf- ...
- Linux命令之tab 键补全
tab 键补全 tab 键可以实现命令及路径等补全,提高输入效率,避免出错 命令补全 用户给定的字符串只有一条惟一对应的命令,直接补全, 两次Tab会给出列表 内部命令: 外部命令:bash根据PAT ...