jQuery火箭图标返回顶部代码

jQuery火箭图标返回顶部代码

滚动滑动条后,查看右下角查看效果。很炫哦!!

适用浏览器:IE8、360、FireFox、Chrome、Safari、Opera、傲游、搜狗、世界之窗.

2 opencv-python核心库模块core(上)

core模块定义了opencv中的基础数据结构和基础运算,是整个库的核心模块。而mat数据结构是opencv中最重要的数据结构,是opencv中图像最常用的存储格式。本章节主要记录opencv的基本数据结构,图像的裁剪和缩放,矩阵的简单运算,图像通道分解合并以及几个有趣的实验。

1 基本数据结构

opencv的基本数据结构有mat数据结构,point数据结构,rect数据结构,size数据结构。

1)在python中,mat类型的对象构造操作可以通过numpy来实现(创建图像矩阵)

如下代码构建全0矩阵m1,然后将所有值初始化为128,还可以用copy进行矩阵拷贝,也可以对图像数据的部分原始值进行修改。

import cv2
import numpy as np        #python中,mat类型的对象通过numpy来实现

m1 = np.zeros([512,512],np.uint8)  #创建全0二维矩阵
m1[:] = 128  #初始化赋值

m2 = m1.copy()   #把m1图像拷贝到m2
m2[128:384,128:384] = 0  #将行,列为128到384的区域像素值赋值为0

cv2.imshow('m2',m2)
cv2.imshow('m1',m1)
cv2.waitKey(0)
cv2.destroyAllWindows()

2 图像的裁剪和缩放

可以对图像矩阵进行裁剪和缩放,裁剪直接用python的切片来完成,缩放可以用opencv的 resize() 函数来操作。resize函数介绍如下:

cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) -> dst

参数说明:

src:原图像;dst:改变大小的目标图像;dsize:输出图像的大小。

fx:width方向的缩放比例;fy:height方向的缩放比例;

interpolation:指定插值的方式,图像resize之后,像素要重新计算,靠这个参数来指定重新计算像素的方式,有以下几种:
INTER_NEAREST - 最邻近插值
INTER_LINEAR - 双线性插值,如果最后一个参数你不指定,默认使用这种方法
INTER_AREA -区域插值,使用像素区域关系进行重采样(效果最好)
INTER_CUBIC - 4x4像素邻域内的双立方插值
INTER_LANCZOS4 - 8x8像素邻域内的Lanczos插值

有两点需要注意:1 dsize和fx/fy不能同时为0。指定dsize的值,让fx和fy直接省略或置0 或者 dsize=None或置 (0,0),指定fx和fy的值,(dsize不可省略,会报错)。2 图像的size是(h,w),而
resize的操作是先w,再h。

import cv2         #图像裁剪和缩放
import numpy as np

img = cv2.imread('cat.jpg')
cv2.imshow('cat',img)

rows = img.shape[0]   #图像的行(高) [h,w,c]
cols = img.shape[1] #图像的列(宽)

img2 = img.copy()    #把img1图像拷贝到img2
img2 = cv2.resize(img2,(int(cols/2),int(rows/2)))  #图像尺寸减小为原来的一半,不是裁剪 [w,h]
cv2.imshow('img2',img2)

img3 = img[0:int(rows/2),0:int(cols/2)]   #图像裁剪为原来的1/4,用切片来裁剪,cropped_image = img[80:280, 150:330]  切片img[高,宽]

cv2.imshow('img3',img3)

cv2.waitKey(0)
cv2.destroyAllWindows()

2)在opencv中,点的定义由point类实现。python语言中,point类型可以由tuple元组表示,然后利用numpy进行点乘和叉乘计算。

import numpy as np     #tuple元组点乘叉乘(向量内积/外积)

point1 = (10,20)
point2 = (2,4)
print(type(point1))  #tuple(元组,有序且不可更改的集合)类型,
# 元组与列表相似,不同之处在于元组的元素不能修改,而列表的元素可以修改。元组使用小括号(),列表使用中括号[]。

res1 = np.dot(point1,point2) #点乘
print('res1',res1)

point3 = (1,2,3)
point4 = (4,5,6)

res2 = np.cross(point3,point4)  #叉乘,输出一个向量,方向垂直于输入两向量形成的平面
print('res2',res2)

3)opencv中定义了矩形的表示类rect,模板类rect定义了顶点坐标,宽高,面积等信息的获取操作,以及矩形是否包含点的判断操作。在python中的rect也是通过tuple类型的数据表示,即左上角坐标点(x,y)和矩形宽高4个值表示的rect为(x,y,w,h)的形式,在需要传入rect数据类型的地方,可以按照tuple类型的数据传入。

4)opencv的很多函数中都需要传入size类型的参数,比如mat类的后置函数为mat(Size size,int type),需要通过size类型对象传入构造矩阵的尺寸。size类型对象包含两个成员变量width和height。python中的size对象也是通过tuple类型的数据表示,即 (w,h) 的形式传入宽高数据的,在需要传入size数据类型的地方,可以按照tuple类型的数据传入。

3 矩阵运算

core模块中提供了图像矩阵的基本运算,opencv对这些基本运算都做了封装,比如四则运算,位运算,比较运算等。

 1)四则运算

加法:dst = add(src1, src2, mask=None)  减法:dst = subtract(src1, src2, mask=None)  乘法:dst = multiply(src1, src2)  除法:dst = divide(src1, src2)

import cv2    #矩阵加减乘除,相当于对矩阵中的每个元素进行对应操作
import numpy as np

m1 = np.array([[1,2,3],[4,5,6],[7,8,9]],dtype=float)  #创建ndarray二维数组(矩阵),数据类型为浮点数
m2 = np.array([[11,12,13],[14,15,16],[17,18,19]],dtype=float)

m_add = cv2.add(m1,m2)   #等同于m_add = m1 + m2
print('add:',m_add)
m_sub = cv2.subtract(m1,m2)  #等同于m_sub = m1 - m2
print('subtract:',m_sub)
m_mul = cv2.multiply(m1,m2)  #等同于m_mul = m1 * m2
print('multiply:',m_mul)
m_div = cv2.divide(m1,m2)   #等同于m_div = m1 / m2
print('divide:',m_div)

m_num = m1+5   #直接加减数字相当于矩阵中的元素都加减该数字
m_num2 = cv2.add(m1,5)

print('m_num:\n',m_num)
print('m_num2:\n',m_num2)

2) 位运算

opencv中定义了位运算函数:

按位与:dst = bitwise_and(src1, src2, mask=None)   按位或:dst = bitwise_or(src1,src2, mask=None)   按位异或:dst = bitwise_xor(src1, src2, mask=None) 非运算:dst = bitwise_not(src, mask=None) 

import cv2  #矩阵/图像位运算
import numpy as np

m1 = np.array([[1,2],[3,1]])
m2 = np.array([[5,3],[4,6]])

m_and = cv2.bitwise_and(m1,m2)   #按位与(转换为二进制,对应位均为1时,结果为1,其余为0)
print('m_and:',m_and)

m_or = cv2.bitwise_or(m1,m2)  #按位或(如果两个相应的二进制位有一个为1,则该结果为1,否则为0)
print('m_or:',m_or)

m_xor = cv2.bitwise_xor(m1,m2) #异或运算(如果两个相应的二进制位值不同则为1,否则为0)
print('m_xor:',m_xor)

m_not = cv2.bitwise_not(m1) #非运算(转换为二进制,对应位取反)
print('m_not:',m_not)

3)代数运算

计算矩阵均值的函数:retval = mean(src,mask=None)   

对矩阵进行归一化:dst = normalize(src, dst, alpha=None, beta=None, norm_type=None, dtype=None, mask=None) alpha表示归一化的上界,beta表示归一化的下界。norm_type表示归一化类型(归一化是机器学习和深度学习很重要的一个技巧,可以减小数据之间的差异对模型训练结果的影响,还可以加速模型收敛)

平方根:dst = sqrt(src)   幂运算:dst = pow(src, power) 也可以直接 src**power   指数运算:dst = exp(src)  对数运算:dst = log(src) 

import cv2
import numpy as np      #矩阵代数运算

m1 = np.array([[1,2,3],[3,4,5]],dtype=float)  

mean_res = cv2.mean(m1)   #矩阵均值返回值类型是tuple,有四个元素,第一个是均值
print('the mean is:',mean_res)
print(type(mean_res))

dst = np.array([])       #均值归一化参数的返回值需要一个对象
norm_res = cv2.normalize(m1,dst,norm_type=cv2.NORM_MINMAX)  #线性归一化
print('norm_res:',norm_res)

sqrt_res = cv2.sqrt(m1)
print('sqrt_res:',sqrt_res) #平方根

pow_res = cv2.pow(m1,3)
print('pow:',(m1)**3)   #幂运算
print('pow_res:',pow_res)  #幂运算

exp_res = cv2.exp(m1)     #指数运算
print('exp_res:',exp_res)

log_res = cv2.log(m1)
print('log_res:',log_res)  #对数运算

 4) 比较运算

两个矩阵的比较:dst = compare(src1, src2, cmpop)  cmpop表示比较方式。(CMP_EQ=0,相等;CMP_GT=1, 大于等于;CMP_GE=2,大于;CMP_LT=3, 小于等于;CMP_LE=4, 小于;CMP_NE=5, 不等于) 求最大值:dst = max(src1, src2)    求最小值:dst = min(src1, src2)   还有一个比较有用的函数:minval, maxval, minloc,maxloc = minMaxLoc(src, mask=None) 可以输出矩阵最大最小值和其对应的位置。

矩阵排序:dst = sort(src, flags) flags表示排序方式,由SortFlags定义。

import cv2
import numpy as np      #矩阵比较运算

m1 = np.array([[1,6,3],[15,12,5]],dtype=float)  
m2 = np.array([[9,5,3],[14,12,16]],dtype=float)

compare_res1 = cv2.compare(m1,m2,cv2.CMP_EQ) #比较两个矩阵对应的元素是否相等,等返回255,不等返回0 
compare_res2 = cv2.compare(m1,m2,cv2.CMP_GT) #判断m1的元素是否大于等于m2,是返回255,非返回0

max_res =cv2.max(m1,m2)  #求两个矩阵中的最大值,元素比较
min_res =cv2.min(m1,m2)  #求两个矩阵中的最小值,元素比较
minmax_loc = cv2.minMaxLoc(m1)  #求矩阵中的最小值,最大值和对应的坐标,不是下标(cv是列优先,(0,2)代表第一列第三行)
                                  #OpenCV读取的图像矩阵坐标与图像坐标系下的坐标横纵正好相反  
    
sort_res = cv2.sort(m1,cv2.SORT_ASCENDING) #升序排序

print('res1:',compare_res1)
print('res2:',compare_res2)
print('max_res:',max_res)
print('min_res:',min_res)
print('minmax_loc:',minmax_loc)
print('sort_res:',sort_res)

print('m1[1][0]:',m1[1][0])

 5)特征值和特征向量

特征值和特征向量在机器学习中很常见,opencv提供了函数eigen来计算对称矩阵的特征值和特征向量,非对称矩阵用eigenNonSymmetric。

retval, eigenvalues, eigenvectors = eigen(src)  retval是返回状态,eigenvalues是返回的特征值,eigenvectors 是返回的特征向量。

opencv提供了生成随机数矩阵的函数randn和randu,randn生成的矩阵服从正态分布,randu生成的矩阵服从均匀分布。dst = randn(dst, mean, stddev) mean表示均值,stddev表示随机数的标准差。dst = randu(dst, low, high) low表示随机数的生成下界,high表示随机数生成的上界。

opencv还提供了将矩阵的行/列视为一组一维向量,并对向量执行指定的操作(REDUCE_AVG=1, 计算均值;REDUCE_MAX=2, 计算最大值;REDUCE_MIN=3, 计算最小值;REDUCE_SUM=0, 计算行/列的和),直到获得单个行/列,从而将矩阵缩减为一个向量。 dst = reduce(src, dim, rtype)  dim为0表示矩阵降维为单行,1表示矩阵降维为单列。

import cv2          #生成随机数矩阵,计算矩阵的特征值和特征向量,矩阵转向量
import numpy as np

m1 = np.zeros((2,3),dtype=np.int) #创建全0矩阵整型
m2 = np.ones((3,3),dtype=np.float) #创建全1矩阵浮点型

m1 = cv2.randn(m1,3,1)  #生成服从正态分布的矩阵,均值3,标准差1
m2 = cv2.randu(m2,1,10)  #生成服从均匀分布的矩阵,下界1,上界10
print('m1:\n',m1,'\nm2:\n',m2)

eigen_res = cv2.eigen(m2)  #计算对称矩阵的特征值和特征向量,矩阵必须是方阵,元素是float
print('eigen_res:\n',eigen_res)

eigen_res2 = cv2.eigenNonSymmetric(m2) ##计算非对称矩阵的特征值和特征向量,矩阵必须是方阵,元素是float
print('eigen_res2:\n',eigen_res2)

img = cv2.imread('./cat.jpg')

dst = cv2.reduce(img,0,cv2.REDUCE_AVG) #矩阵转向量,对矩阵的行/列视为一组向量单独操作(取均值,最大,最小,和),参数0表示降为单行,1为单列
                                          #每行/列返回一个值,从而将矩阵缩减为一个向量

print('dst:',dst.shape)  #将输入矩阵的每一列取均值,组成一个单行的向量
print('cat:',img.shape)

 6)图像通道分离与通道合并

对于一幅RGB格式的图像,包括R,G,B三个通道,opencv提供了通道分离函数split函数,和通道合并函数merge。

通道分离:b,g,r = split(img)    通道合并:dst = merge(mv)   mv = [b,g,r]

import cv2  #图像通道分离/合并
import numpy as np

img = cv2.imread('cat.jpg')


#img[:,:,0]=0  #img[]前两个参数是指的h,w,冒号指全部取得,最后一个参数是指的通道序列号,图像的通道为BGR,分别对应012

b,g,r = cv2.split(img)  #图像通道分离

cv2.imshow('cat',img)
cv2.imshow('img_r',r)  #显示红色通道图像,单通道图像是灰色
cv2.imshow('img_g',g)
cv2.imshow('img_b',b)

g[:] = 0    #绿色图像设置为0  
b[:] = 0    #蓝色图像设置为0  
merge_res = cv2.merge([b,g,r]) #图像通道合并,只剩下红色通道没变,图像会显示红色

cv2.imshow('merge:',merge_res)

cv2.waitKey(0)
cv2.destroyAllWindows()

有趣的事1:对单通道进行运算,用来改变图像的整体颜色:

import cv2   #对图像单通道进行操作

img = cv2.imread('./cat.jpg')
print(img.shape)

b,g,r = cv2.split(img)   

r2 = cv2.add(r,30)  #只增加红色通道的像素值,给图像加红
b2 = cv2.add(r,30)    #只增加蓝色通道的像素值,给图像加蓝

img2 = cv2.merge([b,g,r2])
img3 = cv2.merge([b2,g,r])

#img2 = cv2.add(img,-30)   #用cv的add算法加减,只有第一列r像素值改变了,bg通道像素值不变,且像素值最大255,最小0(加变红紫,减变黄)
#img3 = img - 30    #直接用+号加减数字,所有像素值都改变了,且超过255的像素值对256取余。


cv2.imshow('img',img)
cv2.imshow('red',img2)
cv2.imshow('blue',img3)


cv2.waitKey(0)
cv2.destroyAllWindows()

 

有趣的事2:计算一幅rgb图像中有多少种不同的颜色:

首先,什么是不同的颜色:对rgb图像来说,只要红绿蓝三个通道的任何一个通道的像素值不相同,那么就是不同的颜色。也就是说,要计算有多少中颜色,就是要计算三通道的不同像素值的排列组合有多少种。用split把图像分为三个通道brg,每个通道都是m*n的矩阵,每个矩阵的像素值范围是0-255。统计每个通道(矩阵)内不重复元素的个数(1 可以用count函数统计每个像素值出现的次数,然后相加。2 先用set集合去重,再用len统计个数。3 想要统计每个元素出现的次数,可以使用collections模块提供的Counter函数。4 numpy中的unique()函数可以用来统计一个数组中不同元素的个数,此处使用unique,然后用len计算),然后把三个通道的统计数相乘就可以了。

import cv2
import numpy as np

img = cv2.imread('./cat.jpg')

b,g,r = cv2.split(img)


count_b = len(np.unique(b))
count_g = len(np.unique(g))
count_r = len(np.unique(r))


count = count_b * count_g * count_r
print('color number:',count)      #color number: 16386304

 

有趣的事3:利用进度条实现一个简单的颜色混合器(调色板),即在图像窗口中创建三个进度条,进度条的值为0-255,3个进度条的值对于图像的RGB 3个通道的值,调节进度条可以查看颜色混合后的效果。

opencv提供了创建进度条的函数 createTrackbar,createTrackbar(trackbarName, windowname, minval, maxval, callback)

opencv还提供了用于获取进度条位置的函数 getTrackbarPos,retval = getTrackbarPos(trackbarname, winname)

import cv2
import numpy as np  #利用trackbar显示RGB颜色通道,方法一

cv2.namedWindow('trackbar',cv2.WINDOW_NORMAL)  #定义窗口
cv2.resizeWindow('trackbar',640,480)

def callback(value):   #回调函数(回调函数不做操作)
    pass

cv2.createTrackbar('R','trackbar',0,255,callback) #定义三个trackbar
cv2.createTrackbar('G','trackbar',0,255,callback) 
cv2.createTrackbar('B','trackbar',0,255,callback)

img = np.zeros((480,640,3),np.uint8)  #定义一个全黑图像

while True:
    r = cv2.getTrackbarPos('R','trackbar')  #循环获取trackbar的返回值 
    g = cv2.getTrackbarPos('G','trackbar')
    b = cv2.getTrackbarPos('B','trackbar')
    
    img[:] = [b,g,r]    #给图像的brg三个颜色通道赋值
cv2.imshow('trackbar',img) #显示赋值后的当前图像
if cv2.waitKey(1) == ord('q'): #等待1ms或者键盘输入q进入下一次循环 break cv2.destroyAllWindows()

  可以把获取进度条的值和把值赋给图像的代码放到回调函数中去:

import cv2
import numpy as np  #利用trackbar显示RGB颜色通道,方法二

cv2.namedWindow('trackbar',cv2.WINDOW_NORMAL)
cv2.resizeWindow('trackbar',(640,480))

def callback(pos):
    r = cv2.getTrackbarPos('R','trackbar')  #回调函数(把获取进度条的值放在回调函数中)
    g = cv2.getTrackbarPos('G','trackbar')
    b = cv2.getTrackbarPos('B','trackbar') 
    img[:] = [b,g,r]               #给图像的三个颜色通道赋值
    cv2.imshow('trackbar',img)   #只要trackbar的值改变,就重置图片颜色
    
img = np.zeros((480,640,3),np.uint8)

cv2.createTrackbar('R','trackbar',0,255,callback)
cv2.createTrackbar('G','trackbar',0,255,callback)
cv2.createTrackbar('B','trackbar',0,255,callback)



while True:
    cv2.imshow('trackbar',img)  #循环显示图片
    key = cv2.waitKey(0)
    if key == ord('q'):
        break
cv2.destroyAllWindows()

 两种方法都可以实现拖动进度条来达到颜色混合的目的,如下:

  

 

 利用进度条直接改变图片的颜色呢,比如直接通过进度条来加红加蓝,然后观察效果。

import cv2
import numpy as np  #输入图片,将图片整体加红/加绿/加蓝

cv2.namedWindow('change_color',cv2.WINDOW_NORMAL)
cv2.resizeWindow('change_color',(600,600))

def callback(value):   #回调函数
    pass

cv2.createTrackbar('R','change_color',0,255,callback)  #创建三个进度条
cv2.createTrackbar('G','change_color',0,255,callback)
cv2.createTrackbar('B','change_color',0,255,callback)

img = cv2.imread('./cat.jpg')
    
while True:
    r = cv2.getTrackbarPos('R','change_color')
    g = cv2.getTrackbarPos('G','change_color')
    b = cv2.getTrackbarPos('B','change_color')
    
    img_b,img_g,img_r = cv2.split(img)   #只增加红色通道的像素值,给图像加红
    img_r = cv2.add(img_r,r)
    img2 = cv2.merge([img_b,img_g,img_r])

    img_b,img_g,img_r = cv2.split(img2)   #只增加绿色通道的像素值,给图像加绿
    img_g = cv2.add(img_g,g)
    img3 = cv2.merge([img_b,img_g,img_r])

    img_b,img_g,img_r = cv2.split(img3)   #只增加蓝色通道的像素值,给图像加蓝
    img_b = cv2.add(img_b,b)
    img4 = cv2.merge([img_b,img_g,img_r])    
    
    cv2.imshow('change_color',img4)
    key = cv2.waitKey(1)
    if key == ord('q'):
        break

cv2.destroyAllWindows()
    

  

 

 

 

  

 

 

 

  

 

posted @ 2023-07-05 22:19  寒水浮云  阅读(300)  评论(0编辑  收藏  举报