calcHist计算直方图
void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false )
参数详解:
onst Mat* images:输入图像
int nimages:输入图像的个数
const int* channels:需要统计直方图的第几通道
InputArray mask:掩膜,,计算掩膜内的直方图 …Mat()
OutputArray hist:输出的直方图数组
int dims:需要统计直方图通道的个数
const int* histSize:指的是直方图分成多少个区间,就是 bin的个数
const float** ranges: 统计像素值得区间
bool uniform=true::是否对得到的直方图数组进行归一化处理
bool accumulate=false:在多个图像时,是否累计计算像素值得个数
cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate ]]) #返回hist
参数详解:
第一个参数必须用方括号括起来。
第二个参数是用于计算直方图的通道,这里使用灰度图计算直方图,所以就直接使用第一个通道;
第三个参数是Mask,这里没有使用,所以用None。
第四个参数是histSize,表示这个直方图分成多少份(即多少个直方柱)。第二个例子将绘出直方图,到时候会清楚一点。
第五个参数是表示直方图中各个像素的值,[0.0, 256.0]表示直方图能表示像素值从0.0到256的像素。
最后是两个可选参数,由于直方图作为函数结果返回了,所以第六个hist就没有意义了(待确定) 最后一个accumulate是一个布尔值,用来表示直方图是否叠加。
将时域转换为频域,在频域上对图像进行操作。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('car.jpg', 0)
#numpy
f = np.fft.fft2(img) #傅里叶变换
fshift = np.fft.fftshift(f) #把中点移动到中间去
magnitude_spectrum = 20 * np.log(np.abs(fshift)) #计算每个频率的成分多少
plt.figure(figsize=(10, 10))
plt.subplot(221), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(222), plt.imshow(magnitude_spectrum, cmap='gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
#去掉低频信号,留下高频信号
rows, cols = img.shape
crow, ccol = rows // 2, cols // 2
fshift[crow - 30:crow + 30, ccol - 30:ccol + 30] = 0
#傅里叶逆变换
f_ishift = np.fft.ifftshift(fshift)
img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(img_back)
plt.subplot(223), plt.imshow(img_back, cmap='gray')
plt.title('Image after HPF'), plt.xticks([]), plt.yticks([])
plt.subplot(224), plt.imshow(img_back)
plt.title('Result in JET'), plt.xticks([]), plt.yticks([])
plt.show()
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('car.jpg', 0)
dft = cv2.dft(np.float32(img), flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
magnitude_spectrum = 20 * np.log(cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))
plt.figure(figsize=(10, 10))
plt.subplot(221), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(222), plt.imshow(magnitude_spectrum, cmap='gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
rows, cols = img.shape
crow, ccol = rows // 2, cols // 2
# create a mask first, center square is 1, remaining all zeros
mask = np.zeros((rows, cols, 2), np.uint8)
mask[crow - 30:crow + 30, ccol - 30:ccol + 30] = 1
fshift = dft_shift * mask
# apply mask and inverse DFT
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:, :, 0], img_back[:, :, 1])
plt.subplot(223), plt.imshow(img_back, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(224), plt.imshow(img_back)
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()
根据数学公式,找出图像中对应的形状。(极坐标/直角坐标转换为霍夫空间,再根据数学公式找到符合的形状)
检测直线:cv2.HoughLines(edges, 1, np.pi/180,200)
第一个参数为 边缘提取后的图像
第二、三个参数分别为ρ和θ 的取值精度(极坐标)
第四个参数为阈值(多长的断裂范围判断为同一直线)
检测圆:circle = cv2.HoughCircles(dst, cv2.HOUGH_GRADIENT, 1, 80, param1=40, param2=20, minRadius=20, maxRadius=300)
第一个参数为待检测的图
第二个参数为Hough 变换方式,目前只支持CV_HOUGH_GRADIENT, which is basically 21HT, described in [Yuen03].
第三个参数为累加器图像的分辨率
第四个参数为区分的两个不同圆之间的最小距离
第五、六个参数为双边阈值的参数
第七、八个参数为检测的圆半径范围
void HoughLines( InputArray image,
OutputArray lines,
double rho, // rho 的步长
double theta, // 角度步长
int threshold, // 阈值
double srn=0,
double stn=0 );
void HoughCircles(InputArray image,
OutputArray circles,
int method,
CV_HOUGH_GRADIENT,
double dp,
double minDist,
double param1=100,
double param2=100,
int minRadius=0,
int maxRadius=0 );
实例1:(Python 霍夫变换检测直线)
import cv2
import numpy as np
image = cv2.imread("lines.jpg")
image_2 = image.copy()
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(image_gray, 100, 150)
lines = cv2.HoughLines(edges, 1, np.pi / 180, 150)
for line in lines:
rho, theta = line[0]
a = np.cos(theta)
b = np.sin(theta)
x0 = a * rho
y0 = b * rho
x1 = int(x0 + 1000 * (-b)) # 直线起点横坐标
y1 = int(y0 + 1000 * (a)) # 直线起点纵坐标
x2 = int(x0 - 1000 * (-b)) # 直线终点横坐标
y2 = int(y0 - 1000 * (a)) # 直线终点纵坐标
cv2.line(image, (x1, y1), (x2, y2), (0, 0, 255), 2)
imgs = np.hstack([image_2,image])
cv2.imshow("image_lines", imgs)
cv2.imwrite("test.jpg",imgs)
cv2.waitKey(0)
import cv2
import numpy as np
rawImage = cv2.imread("circles.jpg")
image = cv2.GaussianBlur(rawImage, (3, 3), 1)
image_gray = cv2.cvtColor(image, cv2.COLOR_BGRA2GRAY)
edges = cv2.Canny(image_gray, 100, 150)
circle = cv2.HoughCircles(edges, cv2.HOUGH_GRADIENT, 1, 80, param1=40, param2=20, minRadius=20, maxRadius=100)
if not circle is None:
circle = np.uint16(np.around(circle))
for i in circle[0, :]:
cv2.circle(image, (i[0], i[1]), i[2], (0, 0, 255), 2)
imgs = np.hstack([rawImage,image])
cv2.imshow("image_lines", imgs)
cv2.imwrite("test.jpg",imgs)
cv2.waitKey(0)
根据阈值将图像转化为二值图片。
Python 函数形式:
cv2.threshold(src, thresh, maxval, type[, dst]) → retval, dst
src:表示的是待转化的图片
thresh:表示的是阈值(起始值)
maxval:表示的是最大值
type:表示的是这里划分的时候的算法,常用值为0(cv2.THRESH_BINARY)
C++ 函数形式:
double cv::threshold(
cv::InputArray src, // 输入图像
cv::OutputArray dst, // 输出图像
double thresh, // 阈值
double maxValue, // 向上最大值
int thresholdType // 阈值化操作的类型
);
Python 函数形式:
cv2.adaptiveThreshold(src, maxval, thresh_type, type, Block Size, C) → retval, dst
src: 输入图,只能输入单通道图像,通常来说为灰度图
maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
thresh_type: 阈值的计算方法,包含以下2种类型:cv2.ADAPTIVE_THRESH_MEAN_C; cv2.ADAPTIVE_THRESH_GAUSSIAN_C.
type:二值化操作的类型,与固定阈值函数相同,包含以下5种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV.
Block Size: 图片中分块的大小
C :阈值计算方法中的常数项
C++ 函数形式:
void cv::adaptiveThreshold(
cv::InputArray src, // 输入图像
cv::OutputArray dst, // 输出图像
double maxValue, // 向上最大值
int adaptiveMethod, // 自适应方法,平均或高斯
int thresholdType // 阈值化类型
int blockSize, // 块大小
double C // 常量
);
仿射变换:平移、旋转、放缩、剪切、反射。
cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst
src - 输入图像。
M - 变换矩阵。
dsize - 输出图像的大小。
flags - 插值方法的组合(int 类型!)
borderMode - 边界像素模式(int 类型!)
borderValue - (重点!)边界填充值; 默认情况下,它为0。
void cv::warpAffine(cv::InputArray src, cv::OutputArray dst, cv::InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())
Python:
rot_mat = cv2.getRotationMatrix2D(center, -5, 1)
第一个参数表示旋转中间点的位置,
第二个参数表示旋转的度数,(逆时针旋转5度)
第三个参数表示进行等比列的缩放
C++:
Mat getRotationMatrix2D(Point2f center, double angle, double scale)
透视变换是将图片投影到一个新的视平面,也称作投影映射。
生成透视变换矩阵 M:输入原始图像和变换之后的图像的对应4个点,便可以得到变换矩阵。
M = cv2.getPerspectiveTransform(pts1, pts2)
dst = cv2.warpPerspective(img, M, (200, 201))
Mat getPerspectiveTransform(const Point2f* src, const Point2f* dst)
cv::warpPerspective( InputArray src,
OutputArray dst,
InputArray M,
Size dsize,
int flags = INTER_LINEAR,
int borderMode = BORDER_CONSTANT,
const Scalar& borderValue = Scalar());
void add(InputArray src1, InputArray src2, OutputArray dst,InputArray mask=noArray(), int dtype=-1);//dst = src1 + src2
void subtract(InputArray src1, InputArray src2, OutputArray dst,InputArray mask=noArray(), int dtype=-1);//dst = src1 - src2
void multiply(InputArray src1, InputArray src2,OutputArray dst, double scale=1, int dtype=-1);//dst = scale*src1*src2
void divide(InputArray src1, InputArray src2, OutputArray dst,double scale=1, int dtype=-1);//dst = scale*src1/src2
void divide(double scale, InputArray src2,OutputArray dst, int dtype=-1);//dst = scale/src2
void scaleAdd(InputArray src1, double alpha, InputArray src2, OutputArray dst);//dst = alpha*src1 + src2
void addWeighted(InputArray src1, double alpha, InputArray src2,double beta, double gamma, OutputArray dst, int dtype=-1);//dst = alpha*src1 + beta*src2 + gamma
void sqrt(InputArray src, OutputArray dst);//计算每个矩阵元素的平方根
void pow(InputArray src, double power, OutputArray dst);//src的power次幂
void exp(InputArray src, OutputArray dst);//dst = e**src(**表示指数的意思)
void log(InputArray src, OutputArray dst);//dst = log(abs(src))
void bitwise_and(InputArray src1, InputArray src2,OutputArray dst, InputArray mask=noArray());//dst = src1 & src2
void bitwise_or(InputArray src1, InputArray src2,OutputArray dst, InputArray mask=noArray());//dst = src1 | src2
void bitwise_xor(InputArray src1, InputArray src2,OutputArray dst, InputArray mask=noArray());//dst = src1 ^ src2
void bitwise_not(InputArray src, OutputArray dst,InputArray mask=noArray());//dst = ~src