发现了一个很棒的git,mark一下
https://github.com/android-nuc/StudyPath/blob/master/README.md
找到了一本书《opencv算法精解基于python和C++》
图书馆没有啦不过下载了电子版
对算法进行了解析并且通过python和c++两种语言实现
感觉挺棒的 学习一下试试看
看毛星云那本可以等看完这个再看
// ex2c++.cpp : 定义控制台应用程序的入口点。
//
#include “stdafx.h”
#include
#include
using namespace cv;
int main()
{
//两种定义Mat的方式
Mat m = Mat(Size(2, 3), CV_32FC(1));
Mat n = (Mat_(2, 3) << 1, 2, 3, 4, 5, 6);
std::cout <<"利用Size"<<"\n"<< m<<"\n";
std::cout <<"\n"<<"利用Mat_"<<"\n"<< n<<"\n";
std::cout <<"\n"<< "行" << n.rows;
Size size = m.size();//获取尺寸
std::cout <<"\n"<< "尺寸" << size;
std::cout << "\n" << "利用at/Point获取矩阵数值" << std::endl;
for (int r = 0; r < n.rows; r++)
{
for (int c = 0; c < n.cols; c++)
{
std::cout << n.at(r, c) << ",";//用at时注意只能对n处理,m未规定数字,且rc不要过界否则报内存错误
std::cout << n.at(Point(c, r)) << ",";//用Point时c在前r在后
}
}
std::cout << "\n"<<"利用指针获取矩阵数值" << std::endl;
for (int r = 0; r < n.rows; r++)
{
//获取矩阵n第r行首地址
const int* ptr = n.ptr(r);
for (int c = 0; c < n.cols; c++)
{
std::cout << ptr[c] << "\t";
}
std::cout << std::endl;
}
if (n.isContinuous())//这里不要忘记()获取连续地址内存
{
int *ptr = n.ptr(0);
std::cout << "\n" << "用iscontinue";
for (int k = 0; k < n.rows*n.cols; k++)
{
std::cout << ptr[k];
}
}
//向量类
Vec vi(11, 22, 33);
Vec4f vf(1.2, 3.2, 1.1, 2.3);//即Vec;Vec3d;Vec3b即Vec
std::cout << "\n" << vi.rows;
std::cout << "\n" << vi.cols;
std::cout << "\n" << vi;
std::cout << "\n" << "访问第i个元素" << vi[1];
std::cout << "\n" << vf;
std::cout << "\n" << "向量矩阵";
Mat mm = (Mat_(2, 3) <(r, c) << ",";
}
}
std::cout << "\n" << "采用指针";
for (int r = 0; r < mm.rows; r++)
{
Vec3f* ptr = mm.ptr(r);//第r行的第一个元素
for (int c = 0; c < mm.cols; c++)
{
std::cout << ptr[c] << ",";
}
}
std::cout << "\n" << "采用成员变量data/step";
for (int r = 0; r < mm.rows; r++)
{
for (int c = 0; c < mm.cols; c++)
{
Vec3f *ptr = (Vec3f*)(mm.data + r*mm.step[0] + c*mm.step[1]);
std::cout << *ptr;
std::cout << mm.step[0];//第0维是线 3*4*3=36
std::cout << mm.step[1];//每一维的大小:第1维是点 float四个字节,最低维(点)3(通道)*4(字节)=12
}
}
system("pause");
return 0;
}
for (int r = 0; r < mm.rows; r++)
{
for (int c = 0; c < mm.cols; c++)
{
Vec3f *ptr = (Vec3f*)(mm.data + r*mm.step[0] + c*mm.step[1]);
std::cout << *ptr;
std::cout << mm.step[0];//第0维是线 3*4*3=36
std::cout << mm.step[1];//每一维的大小:第1维是点 float四个字节,最低维(点)3(通道)*4(字节)=12
}
}
也就是说,这个数组内存区是连在一起的,首先先从data(首数值地址)开始,可以看出data地址是0,然后每遍历一个Vec3f,地址往后走3*4(float是四字节的)个地址,然后遍历完一个Vec3f就把*ptr地址更新
Mat matrix = (Mat_(5, 5) << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25);
int r = 1;
int c = 1;
Mat mr = matrix.row(r);//输出第r行
Mat mc = matrix.col(c);//输出第c列
Mat r_range = matrix.rowRange(Range(2, 4));
Mat c_range = matrix.colRange(Range(2, 4));
cout << "\n"<< mr;
cout << "\n"<< mc;
cout << "\n" << r_range;
cout << "\n" << c_range;
**改变矩阵数值**
r_range.at(0,0)=10000;//改变r_range第0行第0列的值
//注意此时matrix第0行第0列的值也变了
使用成员函数clone和copyTo
先
Mat r_range = matrix.rowRange(2,4).clone();
或者
Mat r_range;
matrix.rowRange(2,4).copyTo(r_range)
这两种方式都可以改变r_range值的同时不改变matrix
#include "stdafx.h"
#include
#include
using namespace cv;
using namespace std;
int main()
{
Mat img = imread("D:\\opencvfile\\ex2c++\\1.jpg", CV_LOAD_IMAGE_COLOR);
if (img.empty())
return -1;
string winname = "原图";
namedWindow(winname, WINDOW_AUTOSIZE);
imshow(winname, img);
cvWaitKey(0);//一定要加这句不然图片缓冲不出来
system("pause");
}
显示图片的操作
1 注意路径:C++里一定是双斜杠+双引号
2 注意cvWaitKey(0)这句一定要加
gemm的用法 参考opencv手册
ch4.6 限制对比度的自适应直方图均衡化
原理:自适应直方图均衡化首先将图像划分为不重叠的区域块(tiles),然后对每一个块分
别进行直方图均衡化。显然,在没有噪声影响的情况下,每一个小区域的灰度直方图会
被限制在一个小的灰度级范围内;但是如果有噪声,每一个分割的区域块执行直方图均
衡化后,噪声会被放大。为了避免出现噪声这种情况,提出了“限制对比度”(Contrast
Limiting)[3],如果直方图的bin超过了提前预设好的“限制对比度”,那么会被裁减,然
后将裁剪的部分均匀分布到其他的bin,这样就重构了直方图。如图4-9所示,假设设
置“限制对比度”为40,第四个bin的值为45,该值大于40,然后将多出的45-40=5均匀分布
到每一个bin,重构后的直方图如图(b)所示,接下来利用重构后的直方图进行均衡化操
作。
Python中 sys.argv[]的用法详解
sys.argv[]说白了就是一个从程序外部获取参数的桥梁,这个“外部”很关键,所以那些试图从代码来说明它作用的解释一直没看明白。因为我们从外部取得的参数可以是多个,所以获得的是一个列表(list),也就是说sys.argv其实可以看作是一个列表,所以才能用[]提取其中的元素。其第一个元素是程序本身,随后才依次是外部给予的参数。
https://blog.csdn.net/woailyoo0000/article/details/79310728
限制对比度的自适应直方图均衡化(AHE),解决了全局直方图均衡化(HE)处理后产生的失真和噪声情况
import cv2
import numpy as np
import sys
if __name__=="__main__":
src = cv2.imread("D:\pythonlearning\gamma\img3.jpg")
src = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
clahe = cv2.createCLAHE(clipLimit=1.0,tileGridSize=(8,8))
dst = clahe.apply(src)
cv2.imshow("src",src)
cv2.imshow("clahe",dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
OpenCV Error: Assertion failed (_src.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3)) || _src.type() == (((2) & ((1 << 3) - 1)) + (((1)-1) << 3))) in `anonymous-namespace'::CLAHE_Impl
这个错误解决方案:
convert each frame to grayscale or apply it on each channel
#convert to grayscale
gray_image = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
6 阈值分割
它是一种基于区域的、简单的通过灰度值信息提取形状的技术,因其实现简单、计算量小、性能稳定而成为图像分割中最基本和应用最广泛的分割技术。往往阈值分割后的输出图像只有两种灰度值:255和0,所以阈值分割处理又常称为图像的二值化处理。阈值分割处理过程可以看作眼睛从背景中分离出前景的过程,阈值分割处理主要是根据灰度值信息提取前景,所以对前景物体与背景有较强对比度的图像的分割特别有用。对对比度很弱的图像进行阈值分割,需要先进行图像的对比度增强,然后再进行阈值处理。下面介绍两种常用的阈值分割技术:全局阈值分割和自适应局部阈值分割。
全局阈值,整幅图像采用同一个数作为阈值。这种方法并不适应与所有情况,尤其是当同一幅图像上的不同部分的具有不同亮度时。
这种情况下我们需要采用自适应阈值。此时的阈值是根据图像上的每一个小区域计算与其对应的阈值。
因此在同一幅图像上的不同区域采用的是不同的阈值,从而使我们能在亮度不同的情况下得到更好的结果。
这种方法需要我们指定三个参数,返回值只有一个。
• Adaptive Method- 指定计算阈值的方法。
– cv2.ADPTIVE_THRESH_MEAN_C:阈值取自相邻区域的平均值
– cv2.ADPTIVE_THRESH_GAUSSIAN_C:阈值取值相邻区域的加权和,权重为一个高斯窗口