计算机视觉笔记记录
要求(减色)
对以下减色方法进行测试,比较其运行时间。
方法1:使用整数除法
方法2:使用取模运算符方法
方法3:使用位运算符方法
方法4:使用整数除法和迭代器方法
方法5:使用整数除法和at方法
一、减色过程简要
通过一定的减色算法将图像中每个像素的每个通道的值同时减少
例如:
24位彩色图像颜色总数为256×256×256
如果把每种颜色数量减少到1/8,那么颜色总数就变成32×32×32
二、代码
main函数
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
//减色算法函数处
int main()
{
Mat image = imread("01.jpg");
printf("整数:%lf\n",Co_Red_Div(image));
printf("取模:%lf\n",Co_Red_Mod(image));
printf("位运算:%lf\n",Co_Red_Bit(image));
printf("整数—迭代器:%lf\n", Co_Red_Div_Iter(image));
printf("整数—at:%lf\n", Co_Red_Div_At(image));
waitKey(0);
return 0;
}
方法1:使用整数除法
代码如下(示例):
//整数除法
double Co_Red_Div(Mat image, int div = 64) {
double start = getTickCount();//返回从最近一次电脑开机到当前的时钟周期
int nr = image.rows;
int nc = image.cols*image.channels();
for (int j = 0; j < nr; j++) {
uchar* data = image.ptr<uchar>(j);
for (int i = 0; i < nc; i++) {
data[i] = saturate_cast<uchar>(
data[i] / div * div + div / 2
);
}
}
//imshow("整数", image);
//cv::getTickFrequency()返回每秒的时钟周期数
return (getTickCount() - start) / getTickFrequency();//计算s
}
方法2:使用取模运算符方法
代码如下(示例):
//取模
double Co_Red_Mod(Mat image, int div = 64) {
double start = getTickCount();
int nr = image.rows;
int nc = image.cols*image.channels();
for (int j = 0; j < nr; j++) {
uchar* data = image.ptr<uchar>(j);
for (int i = 0; i < nc; i++) {
data[i] = data[i] -
data[i] % div + div / 2;
}
}
//imshow("整数", image);
return (getTickCount() - start) / getTickFrequency();
}
方法3:使用位运算符方法
减色因子要限定为2的指数,即 div=pow(2,n)
代码如下(示例):
//位运算
double Co_Red_Bit(Mat image, int div = 16) {
double start = getTickCount();
int nr = image.rows;
int nc = image.cols*image.channels();
for (int j = 0; j < nr; j++) {
uchar* data = image.ptr<uchar>(j);
for (int i = 0; i < nc; i++) {
//用来截取像素值的掩码
uchar mask = uchar(0xFF) << 4;//我这div是16,所以为mask0xF0,n=4
*data &= mask;
*data++ += uchar(div) >> 1;
}
}
//imshow("整数", image);
return (getTickCount() - start) / getTickFrequency();
}
方法4:使用整数除法和迭代器方法
代码例如:
//整数—迭代器
double Co_Red_Div_Iter(Mat image, int div = 64) {
double start = getTickCount();
MatIterator_<Vec3b> begin = image.begin<Vec3b>();
MatIterator_<Vec3b> end = image.end<Vec3b>();
for (; begin != end; begin++) {
(*begin)[0] = saturate_cast<uchar>(
(*begin)[0] / div * div + div / 2);
(*begin)[1] = saturate_cast<uchar>(
(*begin)[1] / div * div + div / 2);
(*begin)[2] = saturate_cast<uchar>(
(*begin)[2] / div * div + div / 2);
}
//imshow("整数", image);
return (getTickCount() - start) / getTickFrequency();
}
方法5:使用整数除法和at方法
代码例如:
//整数除法-at方法
double Co_Red_Div_At(Mat image, int div = 64) {
double start = getTickCount();
int nr = image.rows;
int nc = image.cols;
for (int j = 0; j < nr; j++) {
for (int i = 0; i < nc; i++) {
image.at<Vec3b>(j,i)[0]=saturate_cast<uchar>(
image.at<Vec3b>(j, i)[0] / div * div + div / 2
);
image.at<Vec3b>(j, i)[1] = saturate_cast<uchar>(
image.at<Vec3b>(j, i)[1] / div * div + div / 2
);
image.at<Vec3b>(j, i)[2] = saturate_cast<uchar>(
image.at<Vec3b>(j, i)[2] / div * div + div / 2
);
}
}
//imshow("整数", image);
return (getTickCount() - start) / getTickFrequency();
}
三 运行结果
以上算法可能存在越界 用 cv::saturate_cast()
要求(简单的图像运算)
任务1:在网上找两幅图像,其中一幅为雨景图,利用两幅图像的混合产生下雨效果,显示两幅原图以及混合后的图像;
任务2:修改图像亮度,修改任务1结果图像的亮度,并显示结果图像(窗口命名为“增加亮度”或“降低亮度”)
任务3:仍然采用任务1的两幅图像,利用分割与合并图像通道将雨景图加到某个通道上(注意此时雨景图要以灰度图形式读入),并显示处理结果,窗口名为(“x通道叠加效果”,x为红色或绿色或蓝色)
一,简要
图像和普通的矩阵一样可以进行加,减,乘,除运算,因此可以用不同的方式来组合图像二,代码
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat image = imread("01.jpg");
Mat image1 = imread("xiaYu.jpg");
if (image.size() != image1.size())
resize(image1,image1,image.size());
imshow("image", image);
imshow("image1", image1);
Mat result;
//输出混合图
addWeighted(image, 0.7, image1, 0.9, 0, result);
imshow("result", result);
//改变亮度
imshow("降低亮度", result + Scalar(-50, -50, -50));
imshow("增加亮度", result + Scalar(50, 50, 50));
//通道叠加混合图
/*Mat image3 = imread("xiaYu.jpg", IMREAD_GRAYSCALE);
imshow("image3", image3);*/
Mat image2;
//opencv 直接读入的单通道和cvtColor的值不同
//直接读入 可 0 或 IMREAD_GRAYSCALE
//cvtColor COLOR_RGB2GRAY 或 CV_BGR2GRAY
//改变为灰度图,为单通道
cvtColor(image1, image2, COLOR_RGB2GRAY);
//创建包含不同通道的向量
vector<Mat> planes;
//分隔
split(image, planes);
//单通道相加
planes[2] += image2;
//所有通道合拼
merge(planes, result);
imshow("红色通道叠加效果", result);
waitKey(0);
return 0;
}
三,运行结果
要求(简单的图像映射)
利用图像重映射实现任意角度的图像旋转,显示出原图和旋转后的图像(多个不同角度)一,简要
通过移动像素来改变图像的外观二,代码
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include<opencv2/opencv.hpp>
#include <cmath>
#define j2h(x) (3.1415926 * (x) / 180.0)
using namespace cv;
using namespace std;
//波浪效果
void wave(const Mat &image, Mat &result) {
Mat srcX(image.rows, image.cols, CV_32F);
Mat srcY(image.rows, image.cols, CV_32F);
for (int i = 0; i < image.rows; i++) {
float* pSrcX = srcX.ptr<float>(i);
float* pSrcY = srcY.ptr<float>(i);
for (int j = 0; j < image.cols; j++) {
pSrcX[j] = j;
pSrcY[j] = i + 5 * sin(j / 10.0);
}
}
remap(image, result, srcX, srcY, INTER_LINEAR);
}
//水平翻转效果
void waveF(const Mat &image, Mat &result) {
Mat srcX(image.rows, image.cols, CV_32F);
Mat srcY(image.rows, image.cols, CV_32F);
for (int i = 0; i < image.rows; i++) {
float* pSrcX = srcX.ptr<float>(i);
float* pSrcY = srcY.ptr<float>(i);
for (int j = 0; j < image.cols; j++) {
pSrcX[j] = image.cols-j-1;
pSrcY[j] = i;
}
}
remap(image, result, srcX, srcY, INTER_LINEAR);
}
//旋转效果
void waveX(const Mat &image, Mat &result, double angle) {
Mat srcX(image.rows, image.cols, CV_32F);
Mat srcY(image.rows, image.cols, CV_32F);
int cenx ,ceny;
double sinValue = sin(j2h(angle));
double cosValue = cos(j2h(angle));
for (int i = 0; i < image.rows; i++) {
float* pSrcX = srcX.ptr<float>(i);
float* pSrcY = srcY.ptr<float>(i);
for (int j = 0; j < image.cols; j++) {
cenx = j - image.cols / 2;
ceny = i - image.rows / 2;
pSrcX[j] = cenx * cosValue + ceny * sinValue +
image.cols / 2;
pSrcY[j] = ceny * cosValue - cenx * sinValue +
image.rows / 2;
}
}
remap(image, result, srcX, srcY, INTER_LINEAR);
}
int main()
{
Mat image = imread("01.jpg");
Mat result;
//wave(image, result);
//waveF(image, result);
waveX(image, result,-60);
imshow("波浪形", result);
waitKey(0);
return 0;
}