2023年上半年,一直在学习opencv-c++版本,学习了其中的多个库函数
笔记链接:https://www.cnblogs.com/Tan-code/category/2339311.html
- opencv-python 读取图片,画圆等基本操作 :
- opencv-c++ 多个库函数:
- opencv-python与opencv-c++ 结合理解:
结合两段代码来比较实现:
# 导入所需模块
import cv2
from matplotlib import pyplot as plt
import os
import numpy as np
# plt显示彩色图片
def plt_show0(img):
#cv2与plt的图像通道不同:cv2为[b,g,r];plt为[r, g, b]
b,g,r = cv2.split(img)
img = cv2.merge([r, g, b])
plt.imshow(img)
plt.show()
# plt显示灰度图片
def plt_show(img):
plt.imshow(img,cmap='gray')
plt.show()
# 图像去噪灰度处理
def gray_guss(image):
image = cv2.GaussianBlur(image, (3, 3), 0)
gray_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
return gray_image
# 读取待检测图片
origin_image = cv2.imread('E:\opencv_practice\licenses.jpg')
# 复制一张图片,在复制图上进行图像操作,保留原图
image = origin_image.copy()
# 图像去噪灰度处理
gray_image = gray_guss(image)
# x方向上的边缘检测(增强边缘信息)
Sobel_x = cv2.Sobel(gray_image, cv2.CV_16S, 1, 0)
absX = cv2.convertScaleAbs(Sobel_x)
image = absX
# 图像阈值化操作——获得二值化图
ret, image = cv2.threshold(image, 0, 255, cv2.THRESH_OTSU)
# 显示灰度图像
#plt_show(image)
# 形态学(从图像中提取对表达和描绘区域形状有意义的图像分量)——闭操作
kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 10))
image = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernelX,iterations = 1)
# 显示灰度图像
#plt_show(image)
# 腐蚀(erode)和膨胀(dilate)
kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (50, 1))
kernelY = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 20))
#x方向进行闭操作(抑制暗细节)
image = cv2.dilate(image, kernelX)
image = cv2.erode(image, kernelX)
#y方向的开操作
image = cv2.erode(image, kernelY)
image = cv2.dilate(image, kernelY)
# 中值滤波(去噪)
image = cv2.medianBlur(image, 21)
# 显示灰度图像
#plt_show(image)
# 获得轮廓
contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
width,height = 600,350 #所需图像大小
for item in contours:
rect = cv2.boundingRect(item)
x = rect[0]
y = rect[1]
weight = rect[2]
height = rect[3]
# 根据轮廓的形状特点,确定车牌的轮廓位置并截取图像,否则提取不到车牌轮廓
if (weight > (height * 3.5)) and (weight < (height * 4)):
image = origin_image[y:y + height, x:x + weight]
# 将车牌图像进行透视变换,矫正为矩形形状
pts1 = np.float32([[0, 0], [weight, 0], [0, height], [weight, height]])
pts2 = np.float32([[0, 0], [width, 0], [0, height], [width, height]])
matrix = cv2.getPerspectiveTransform(pts1, pts2)
warped_image = cv2.warpPerspective(image, matrix, (width, height))
plt_show0(warped_image)
cv2.imwrite('E://RM24暑假考核//rect//licenses.jpg',warped_image)
这是c++版的:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void plt_show0(Mat img) {
Mat bgr_img;
cvtColor(img, bgr_img, COLOR_RGB2BGR);
imshow("Image", bgr_img);
waitKey(0);
}
void plt_show(Mat img) {
imshow("Image", img);
waitKey(0);
}
Mat gray_guss(Mat image) {
Mat gray_image;
GaussianBlur(image, image, Size(3, 3), 0);
cvtColor(image, gray_image, COLOR_RGB2GRAY);
return gray_image;
}
int main() {
Mat origin_image = imread("E:\\opencv_practice\\licenses.jpg");
Mat image = origin_image.clone();
Mat gray_image = gray_guss(image);
Mat Sobel_x,absX;
Sobel(gray_image, Sobel_x, CV_16S, 1, 0);
convertScaleAbs(Sobel_x,absX);
image = absX;
threshold(image, image, 0, 255, THRESH_OTSU);
Mat kernelX = getStructuringElement(MORPH_RECT, Size(30, 10));
morphologyEx(image,image, MORPH_CLOSE, kernelX);
kernelX = getStructuringElement(MORPH_RECT, Size(50, 1));
Mat kernelY = getStructuringElement(MORPH_RECT, Size(1, 20));
dilate(image,image, kernelX);
erode(image, image,kernelX);
erode(image, image,kernelY);
dilate(image, image,kernelY);
medianBlur(image,image, 21);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(image.clone(), contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
int width = 600;
int height = 350;
for (const auto& item : contours) {
Rect rect = boundingRect(item);
int x = rect.x;
int y = rect.y;
int weight = rect.width;
int height = rect.height;
if (weight > (height * 3.5) && weight < (height * 4)) {
image = origin_image(Rect(x, y, weight, height));
Mat pts1 = (Mat_<float>(4, 2) << 0, 0, weight, 0, 0, height, weight, height);
Mat pts2 = (Mat_<float>(4, 2) << 0, 0, width, 0, 0, height, width, height);
Mat matrix = getPerspectiveTransform(pts1, pts2);
Mat warped_image;
warpPerspective(image, warped_image, matrix, Size(width, height));
plt_show0(warped_image);
imwrite("E://RM24暑假考核//rect//licenses.jpg", warped_image);
}
}
return 0;
}
上面两段代码是关于框出车牌的
个人观点:
python代码中,是不会提前声明一个变量的,而是用的时候直接 img = ...
也就是说,绝大多数函数是有返回值的
而c++不同,许多函数 void function(InputArray,OutputArray,....) ,dstimg是直接写到API里的
但是有些函数还是有返回值的
像是代码中的:
Mat matrix = getPerspectiveTransform(pts1, pts2);
Rect rect = boundingRect(item);
这里还学到个新函数:
image = origin_image(Rect(x, y, weight, height));
这行代码是从原始图像(origin_image
)中提取一个矩形区域(Rect
)并保存到新的图像变量 image
中。Rect(x, y, width, height)
表示一个矩形,其中 (x, y)
是矩形的左上角坐标,width
是矩形的宽度,height
是矩形的高度。这样,origin_image(Rect(x, y, width, height))
就表示从 origin_image
中裁剪出指定矩形区域的图像数据,并将其赋值给 image
变量。