python opencv ROI 与copyTo,数学运算的应用
#!/usr/bin/env python3# -*- coding: utf-8 -*-# @Author: tcy# @Date:2020-5-3 12:10:53# @Version:V1.01# @Last Modified by:tcyshanghai songjiang xiaokunshan# @Last Modified time: 2020-5-7 ...
·
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: tcy
# @Date: 2020-5-3 12:10:53
# @Version:V1.01
# @Last Modified by: tcy shanghai songjiang xiaokunshan
# @Last Modified time: 2020-5-7 16:00:00
import cv2,numpy as np
class Array:
def __init__(self):pass
def __del__(self):pass
def add(self,src1,src2,dst=None,mask=None,dtype=None):
if dtype:
return cv2.add(src1,src2,dst,mask,dtype)
else:
return cv2.add(src1,src2,dst,mask)
def addWeighted(self,src1,alpha,src2,beta,gamma=0,dst=None,dtype=None):
if dtype:
return cv2.addWeighted(src1,alpha,src2,beta,gamma,dst,dtype)
else:
return cv2.addWeighted(src1,alpha,src2,beta,gamma,dst)
def sub(self,src1,src2,dst=None,mask=None,dtype=None):
if dtype:
return cv2.subtract(src1,src2,dst,mask,dtype)
else:
return cv2.subtract(src1,src2,dst,mask)
def mul(self,src1,src2,dst=None,scale=None,dtype=None):
"""
multiply(src1, src2[, dst[, scale[, dtype]]]) -> dst
. @brief Calculates the per-element scaled product of two arrays.
.
. The function multiply calculates the per-element product of two arrays:
. There is also a @ref MatrixExpressions -friendly variant of the first function. See Mat::mul .
. For a not-per-element matrix product, see gemm .
.
. @note Saturation is not applied when the output array has the depth
. CV_32S. You may even get result of an incorrect sign in the case of overflow.
. @param src1 first input array.
. @param src2 second input array of the same size and the same type as src1.
. @param dst output array of the same size and type as src1.
. @param scale optional scale factor.
. @param dtype optional depth of the output array
. @sa add, subtract, divide, scaleAdd, addWeighted, accumulate, accumulateProduct, accumulateSquare,
. Mat::convertTo
"""
if dtype:
if scale:
return cv2.multiply(src1,src2,dst,scale,dtype)
else:
return cv2.multiply(src1,src2,dst,dtype=dtype)
else:
if scale:
return cv2.multiply(src1,src2,dst,scale)
else:
return cv2.multiply(src1,src2,dst)
def div(self,src1,src2,dst=None,scale=None,dtype=None):
"""
divide(src1, src2[, dst[, scale[, dtype]]]) -> dst
. @brief Performs per-element division of two arrays or a scalar by an array.
.
. The function cv::divide divides one array by another:
. \f[\texttt{dst(I) = saturate(src1(I)*scale/src2(I))}\f]
. or a scalar by an array when there is no src1 :
. \f[\texttt{dst(I) = saturate(scale/src2(I))}\f]
.
. Different channels of multi-channel arrays are processed independently.
. For integer types when src2(I) is zero, dst(I) will also be zero.
.
. @note In case of floating point data there is no special defined behavior for zero src2(I) values.
. Regular floating-point division is used.
. Expect correct IEEE-754 behaviour for floating-point data (with NaN, Inf result values).
.
. @note Saturation is not applied when the output array has the depth CV_32S. You may even get
. result of an incorrect sign in the case of overflow.
. @param src1 first input array.
. @param src2 second input array of the same size and type as src1.
. @param scale scalar factor.
. @param dst output array of the same size and type as src2.
. @param dtype optional depth of the output array; if -1, dst will have depth src2.depth(), but in
. case of an array-by-array division, you can only pass -1 when src1.depth()==src2.depth().
. @sa multiply, add, subtract
"""
if dtype:
if scale:
return cv2.divide(src1,src2,dst,scale,dtype)
else:
return cv2.divide(src1,src2,dst,dtype=dtype)
else:
if scale:
return cv2.divide(src1,src2,dst,scale)
else:
return cv2.divide(src1,src2,dst)
def bit_and(self,src1,src2,dst=None,mask=None):
return cv2.bitwise_and(src1,src2,dst,mask)
def bit_or(self,src1,src2,dst=None,mask=None):
return cv2.bitwise_or(src1,src2,dst,mask)
def bit_not(self,src,dst=None,mask=None):
return cv2.bitwise_not(src,dst,mask)
def bit_xor(self,src1,src2,dst=None,mask=None):
return cv2.bitwise_xor(src1,src2,dst,mask)
def pow(self,src,power,dst=None):# 乘方
return cv2.pow(src,power,dst)
def sqrt(self,src,dst=None): # 开方
return cv2.sqrt(src,dst)
def max(self,src1,src2,dst=None):# 最大值
return cv2.max(src1,src2,dst)
def min(self,src1,src2,dst=None):# 最大值
return cv2.min(src1,src2,dst)
def meanstd(self,image,mean=None,stddev=None,mask=None):
image=cv2.imread(image,0) if isinstance(image,str) else image
channels=len(image.shape)
if channels==3:
image=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
result=cv2.meanStdDev(image,mean,stddev,mask)
return result[0][0][0],result[1][0][0]
def test_add(self,gray1,gray2):
gray1=cv2.imread(gray1) if isinstance(gray1,str) else gray1
gray2=cv2.imread(gray2) if isinstance(gray2,str) else gray2
result = self.add(gray1,gray2)
result = self.sub(gray1,gray2)
result=self.mul(gray1,gray2,None)
result=self.div(gray1,gray2,None)
result = self.bit_and(gray1,gray2)
result = self.bit_or(gray1,gray2)
result = self.bit_not(gray1)
result = self.bit_xor(gray1,gray2)
result = self.max(gray1,gray2)
result = self.min(gray1,gray2)
print('dtype.name=',gray1.dtype.name)
print('meanstd=',self.meanstd(gray1))#(43.09787760416667, 60.29981335200884)
cv2.imshow("result",result)
cv2.waitKey(0)
def getChannels(self,image):
return len(image.shape)
def getCenterPoint(self,image):
h,w=image.shape[0:2]
cx,cy=int(w*0.5),int(h*0.5)
return cx,cy
def getRectPt1Pt2(self,center:'cx,xy',w:int,h:int):
cx,cy=center
pt1=(int(cx-0.5*w),int(cy-0.5*h))
pt2=(int(cx+0.5*w),int(cy+0.5*h))
return pt1,pt2
def bitplane(self,image, channel:'int'=0, n_RD:'int'=7, value=255)->np.ndarray: # 灰度图:位平面提取
"""
灰度图:位平面提取
"""
img = image if type(image) == type(np.ndarray(())) else cv2.imread(image)
img = img[:, :, channel] if len(img.shape) == 3 else img
r, c = img.shape
x = np.zeros((r, c, 8), dtype=np.uint8)
for i in range(8): # a7权重最高
x[:, :, i] = 2 ** i
r = np.zeros((r, c, 8), dtype=np.uint8)
r[:, :, n_RD] = cv2.bitwise_and(img, x[:, :, n_RD])
mask = r[:, :, n_RD] > 0 # 阈值处理
r[mask] = value
return r[:, :, n_RD]
def bitplane1(self,image, channel:'int'=0, n_RD:'int'=7, value=255)->np.ndarray: # 灰度图:位平面提取
"""
灰度图:位平面提取
将像素右移动n位,对2取模
"""
img = image if type(image) == type(np.ndarray(())) else cv2.imread(image)
img = img[:, :, channel] if len(img.shape) == 3 else img
img = np.right_shift(img, n_RD)
img = np.mod(img, 2)
mask = img[:, :] > 0 # 阈值处理
img[mask] = value
return img
def inRange(self, src: 'np.ndarray', lowerb, upperb) -> np.ndarray:#可处理彩色图
"""
inRange(src, lowerb, upperb[, dst]) -> dst
作用: 【gray二值化,生成mask;colorimage看不出什么用途?】
实现多通道二值化功能;实现对目前区域的提取与分割
在两个阈值内的像素值设置为白色255,而不在阈值区间内的像素值设置为黑色0,该功能类似于之间所讲的双阈值化操作。
:param src: ndarray 原图
:param lowerb: 下边界的数组或标量--图像中低于这个lower_red的值,图像值变为0
:param upperb: 上边界数组或标量--图像中高于这个upper_red的值,图像值变为0
:return: ndarray 输出图像--value 在[lowerb,upperb]范围内时=255,不在=0
与输入图像src 尺寸相同且为CV_8U 类型。
处理方式:
单通道:cv2.inRange(gray,127,200)生成了一幅二值化的输出图像
多通道:
lower = np.array([20, 20, 20],dtype=np.uint8)#不能为标量
higher= np.array([200, 200, 200],dtype=np.uint8)
result=cv2.inRange(arr2,lower,higher)
"""
return cv2.inRange(src,lowerb,upperb)
def copy(self,mat,order='C'):#图像复制:彩色 0.0562 ms
"""
:param mat: ndarray
:param order: str "C"
:return: ndarray
"""
return mat.copy(order)
def copyTo(self,src,mask:'(row1,row2,cols1,col2)'=None):
"""
:param src: source image color or gray.
:param mask: int,int,int,int choose the ROI range.
:return: get the ROI range image.outside ROI is 0.
cv2.copyTo(src,mask)
用途:将小图像拷贝到大图像中
:param src: 原图与模板进行运算后得到的结果拷贝给dst
:param mask: 必须为CV_8U,可以是单通道也可以是多通道
:return: ndarray
说明:
拷贝后仅仅有ROI区域的图形,且图形不在中心
深拷贝,复制了矩阵头和矩阵数据
mask=np.zeros(img2_copy.shape,dtype=img2_copy.dtype)
mask[x_1:x_2,y_1:y_2]=255
img3=cv2.copyTo(img2_copy,mask)
"""
img1=cv2.imread(src) if isinstance(src,str) else src
if mask==None:return img1.copy()
r1,r2,c1,c2=mask
mask=np.zeros(img1.shape,dtype=img1.dtype)
mask[r1:r2,c1:c2]=255
return cv2.copyTo(src,mask)
def __get_mask_image_same_centerPoint(self,mask,image):
r1,r2,c1,c2=mask
dr_mask,dc_mask=abs(r2-r1),abs(c2-c1)
cx,cy=self.getCenterPoint(image)
r1,r2=int(cy-dr_mask*0.5),int(cy+dr_mask*0.5)
c1,c2=int(cx-dc_mask*0.5),int(cx+dc_mask*0.5)
return r1,r2,c1,c2
def copyROI(self,src,src2,mask:'(row1,row2,cols1,col2)',pt1:'(int,int)'=None,center=True):
"""
:param src: 要拷贝选择区域的图像
:param src2: 背景图像
:param mask: src图像中选择的ROI
:param pt1: 将ROI图像放置在结果图指定的左上角(行,列)忽略center
:param center: 当pt1=None时若为True ROI放置在中心,佛则原来位置
:return:ndarray
"""
img1=cv2.imread(src) if isinstance(src,str) else src
img2=cv2.imread(src2) if isinstance(src2,str) else src2
r1,r2,c1,c2=mask
roi=img1[r1:r2,c1:c2]
if pt1:
r1,r2,c1,c2=(pt1[0],pt1[0]+abs(r2-r1),pt1[1],pt1[1]+abs(c2-c1))
else:
r1,r2,c1,c2=self.__get_mask_image_same_centerPoint(mask,img2) if center else mask
img2[r1:r2,c1:c2]=roi
return img2
def imageCenterPointRect(self,img,rect:'pt1,pt2',center:'cx,xy'=None,xoffset:int=None,yoffset:int=None):
"""
:param ceter: 将矩形定位在图像指定的中心点或指定相对图像左上角0,0的偏移量
:param w: mask矩形宽带
:param h: mask矩形高度
:return: 矩形右上左下角中心点坐标pt1,pt2,pt
"""
if len(rect)==2:
pt1,pt2=rect
w_rect,h_rect=abs(pt2[0]-pt1[0]),abs(pt2[1]-pt1[1])
elif len(rect)==4:
x1,y1,x2,y2=rect
w_rect,h_rect=abs(x2-x1),abs(y2-y1)
else:
raise Exception("Parameter rect error!")
if center:
cx,cy=center
elif bool(xoffset) and bool(yoffset):
cx,cy=int(xoffset+0.5*w_rect),(yoffset+0.5*h_rect)
else:
if not isinstance(img,np.ndarray):
raise Exception("Parameter img error!")
cx,cy=int(img.shape[1]/2),int(img.shape[0]/2)
pt=(cx,cy)
pt1=(int(cx-0.5*w_rect),int(cy-0.5*h_rect))
pt2=(int(cx+0.5*w_rect),int(cy+0.5*h_rect))
h,w=img.shape[0:2]
b1=pt[0]>w or pt[1]>h
b2=pt1[0]>w or pt1[1]>h
b3=pt2[0]>w or pt2[1]>h
if b1 or b2 or b3:
raise Exception("Th_recte rect out th_recte range !")
return pt1,pt2,pt
def test_copy(self,img1,img2):
img1=cv2.imread(img1) if isinstance(img1,str) else img1
img2=cv2.imread(img2) if isinstance(img2,str) else img2
channels1,channels2=len(img1.shape),len(img2.shape)
if channels1==3:
img11=cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)
if channels2==3:
img12=cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
print('img1.shape=',img1.shape,img2.shape,img11.shape,img12.shape)
# (480, 640, 3) (480, 640, 3) (480, 640) (480, 640)
#test copy
tmp1=self.copy(img1)
tmp2=self.copy(img11)
cv2.imshow('s1',img1)
cv2.imshow('s2',tmp1)
cv2.imshow('s3',img11)
cv2.imshow('s4',tmp2)
print('tmp1.shape=',tmp1.shape,tmp2.shape)#(480, 640, 3) (480, 640)
#test copyTo
tmp3=self.copyTo(img1,(200,400,0,500))
tmp4=self.copyTo(img11,(200,400,0,500))
cv2.imshow('s1',img1)
cv2.imshow('s2',tmp3)
cv2.imshow('s3',img11)
cv2.imshow('s4',tmp4)
print('tmp3.shape=',tmp3.shape,tmp4.shape)#(480, 640, 3) (480, 640)
#test copyROI()
tmp5=self.copyROI(img1,img2,(200,400,0,500),center=False)
tmp6=self.copyROI(img11,img12,(200,400,0,500),center=False)
cv2.imshow('s1',img1)
cv2.imshow('s2',tmp5)
cv2.imshow('s3',img11)
cv2.imshow('s4',tmp6)
print('tmp5.shape=',tmp3.shape,tmp4.shape)#(480, 640, 3) (480, 640)
tmp7=self.copyROI(img1,img2,(200,400,0,500))
tmp8=self.copyROI(img11,img12,(200,400,0,500))
cv2.imshow('s1',img1)
cv2.imshow('s2',tmp7)
cv2.imshow('s3',img11)
cv2.imshow('s4',tmp8)
tmp7=self.copyROI(img1,img2,(200,400,0,500),(100,0))
tmp8=self.copyROI(img11,img12,(200,400,0,500),(100,0))
cv2.imshow('s1',img1)
cv2.imshow('s2',tmp7)
cv2.imshow('s3',img11)
cv2.imshow('s4',tmp8)
cv2.waitKey()
def test_inRange(self):
from Image.data import Data
arr1=Data.Data.arr2D
arr2=Data.Data.arr3D
print(arr1)
print('==============')
print(a.inRange(arr1,23,33))
"""
[[11 12 13 14]
[21 22 23 24]
[31 32 33 34]]
==============
[[ 0 0 0 0]
[ 0 0 255 255]
[255 255 255 0]]
"""
def ROI(self,img,pt1,pt2):
"""
:param img: np.ndarray or str
:param pt1: rect top left corner
:param pt2:rect right down corner
:return:ndarray
"""
img=cv2.imread(img,1) if isinstance(img,str) else img
mask = np.zeros(img.shape[:2], dtype="uint8")
mask[pt1[0]:pt2[0],pt1[1]:pt2[1]]=255
return cv2.bitwise_and(img, img,mask)
def ROI_1(self,img,pt1,pt2):
"""
:param img: np.ndarray or str
:param pt1: rect top left corner
:param pt2:rect right down corner
:return:ndarray
"""
img=cv2.imread(img,1) if isinstance(img,str) else img
mask = np.zeros(img.shape[:2], dtype="uint8")
cv2.rectangle(mask,pt1,pt2,255,-1)
return cv2.bitwise_and(img, img, mask=mask)
def ROI_2(self,img,row1,row2,col1,col2):
"""
返回选择区域的图像彩色或灰度 rows=row2-row1,cols=col2-col1
"""
img=cv2.imread(img,1) if isinstance(img,str) else img
return img[row1:row2,col1:col2]
def test_ROI(self,image):
pt1,pt2=(500,250),(300,5)
img=self.ROI(image,pt1,pt2)
img1=self.ROI1(image,pt1,pt2)
cv2.imshow('s1',img)
cv2.imshow('s2',img1)
cv2.waitKey()
#===========================================================================================
if __name__=="__main__":
import os
girl=os.getcwd()+'\\data\\girl.jpg'
flower=os.getcwd()+'\\data\\flower.jpg'
gray1=os.getcwd()+'\\data\\fastener1.jpg'
gray2=os.getcwd()+'\\data\\fastener2.jpg'
a=Array()
a.test_add(gray1,gray2)
a.test_ROI(girl)
a.test_ROI(gray1)
a.test_inRange()
a.test_copy(girl,flower)
更多推荐
所有评论(0)