/*腐蚀、模糊、边缘检测、读取视频、调用摄像头 */
#include "stdafx.h"
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
/* 腐蚀操作
Mat img = imread("1.jpg");
imshow("picture", img);
Mat element = getStructuringElement(MORPH_ELLIPSE, Size(20, 20));
Mat dst;
erode(img, dst,element);
imshow("picture2", dst);
waitKey(0);
*/
/* 模糊
Mat img = imread("1.jpg");
imshow("picture", img);
Mat dst;
blur(img, dst, Size(10, 7));
imshow("picture2", dst);
waitKey(0);
*/
/*边缘检测
Mat img = imread("1.jpg");
imshow("picture", img);
Mat dst,edge;
cvtColor(img, dst, CV_BGR2GRAY); //转为灰度图像
blur(dst, edge, Size(3,3)); // 使用3x3内核降噪
Canny(edge, edge, 3, 9, 3); //边缘检测方法,梯度阈值3-9,算子大小3*3的矩阵
imshow("picture2", edge);
waitKey(0);
*/
/*读取视频
VideoCapture capture("1.avi");
while (1)
{
Mat frame;
我capture >> frame;
imshow("video", frame);
waitKey(30);
}
*/
VideoCapture capture(0);
Mat edges;
while (1) {
Mat frame;
capture >> frame;
cvtColor(frame, edges, CV_BGR2GRAY);
blur(edges, edges, Size(7, 7));
Canny(edges, edges, 0, 30, 3);
imshow("摄像头", edges);
waitKey(10);
}
return 0;
}
/**********合成图片 *************/
int main()
{
Mat panda = imread("1.jpg");
/*namedWindow("熊猫");
imshow("熊猫", panda);*/
Mat logo = imread("logo.png");
/*namedWindow("Logo");
imshow("Logo", logo);*/
Mat imageROI;
imageROI = panda(Rect(600, 330, logo.cols, logo.rows)); //Rect前两个参数设置logo全局位置,后两个参数为logo大小
//imageROI = panda(Range(150,150+logo.rows), Range(400, 400 + logo.cols));
addWeighted(imageROI, 0.7, logo, 0.7,0.0, imageROI); //设置权重(logo透明度),微调常数,输出容器
namedWindow("合成");
imshow("合成", panda);
imwrite("输出图像.jpg", panda);
waitKey(0);
return 0;
}
/* 利用轨迹条控制两幅尺寸相等的图片混合*/
#include "stdafx.h"
#include <opencv2/opencv.hpp>
using namespace cv;
#define WINDOW_NAME "线性混合示例"
const int g_nMaxAlphaValue = 100; //Alpha最大值
int g_nAlphaValueSlider; //滑动条对应的变量
double g_fAlohaValue;
double g_fBetaValue;
//声明存储图像的变量
Mat g_srcImage1;
Mat g_srcImage2;
Mat g_dstImage;
/*响应滑动条的回调函数*/
void on_Trackbar(int , void * )
{
g_fAlohaValue = (float)g_nAlphaValueSlider / g_nMaxAlphaValue; //求所占比例
g_fBetaValue = (1.0 - g_fAlohaValue);
addWeighted(g_srcImage1, g_fAlohaValue, g_srcImage2, g_fBetaValue,0.0,g_dstImage);
imshow(WINDOW_NAME, g_dstImage);
}
int main(int argc, char **argv)
{
g_srcImage1 = imread("1.jpg");
g_srcImage2 = imread("2.jpg");
if (!g_srcImage1.data) {
printf("读取第一幅图片错误,请确定图片是否存在\n");
}
if (!g_srcImage2.data) {
printf("读取第二幅图片错误,请确定图片是否存在\n");
}
// 设置滑动条初值为70
g_nAlphaValueSlider = 60;
//创建窗体
namedWindow(WINDOW_NAME, 1);
//在创建的窗体中创建一个滑动条控件
char TrackbarName[50];
sprintf_s(TrackbarName, "透明值");
createTrackbar(TrackbarName,WINDOW_NAME,&g_nAlphaValueSlider,g_nMaxAlphaValue,on_Trackbar);
//结果在回调函数中显示
on_Trackbar(g_nAlphaValueSlider, 0);
waitKey(0);
return 0;
}
/* 绘画彩框 */
/* 绘画彩框*/
#include "stdafx.h"
#include <opencv2/opencv.hpp>
using namespace cv;
#define WINDOW_NAME "绘画彩框"
/*声明全局函数*/
void on_MouseHandle(int event, int x, int y, int flags, void *param);
void DrawRectangle(cv::Mat & img, cv::Rect box);
void ShowHelpText();
/*全局变量*/
Rect g_rectangle;
bool g_bDrawingBox = false; //是否进行绘制
RNG g_rng(12345);
int main(int argc, char ** argv)
{
g_rectangle = Rect(-1, -1, 0, 0);
Mat srcimage(600, 800, CV_8UC3), tempImage; //CV_8UC1,CV_8UC2,CV_8UC3分别表示1通道,2通道,3通道
srcimage.copyTo(tempImage);
g_rectangle = Rect(-1, -1, 0, 0);
srcimage = Scalar::all(255); //设置背景颜色0~255
namedWindow(WINDOW_NAME);
setMouseCallback(WINDOW_NAME, on_MouseHandle, (void*)&srcimage);
/*void setMousecallback(const string& winname, MouseCallback onMouse, void* userdata=0)
winname:窗口的名字
onMouse:鼠标响应函数,回调函数。指定窗口里每次鼠标时间发生的时候,被调用的函数指针。 这个函数的原型应该为void on_Mouse(int event, int x, int y, int flags, void* param);
userdate:传给回调函数的参数 ,(void*)&srcimage意思为将 srcimage的地址强制转化为void*类型,即void指针类型。
指针知识补充:
void * fun( ) ; //声明一个返回值是任意类型的指针 的函数fun()
void vfun( ) ; //声明一个没有返回值的函数vfun()
void (*)( ) 这是一种变量类型,可用来定义函数指针变量,如:
void (*pfun)( ) ; //声明一个函数指针变量pfun,该类型函数就是void vfun( ) 这种类型,pfun可以指向这类函数,如:pfun=vfun ;
参考代码:
#include <stdio.h>
void foo( void )
{
printf("date: %s\n", __DATE__ );
}
void main()
{
void (*p)( void ) ;
p=foo ; //指向该函数
p();//调用方法1
(*p)(); //调用方法2
foo();
}
*/
while (1) {
/*使绘制时可看到矩阵即时拉动情况,此时实际上是在源图的基础上不断重画tempImage,而源图实际被绘制的时刻是鼠标UP时*/
srcimage.copyTo(tempImage);
if (g_bDrawingBox)DrawRectangle(tempImage, g_rectangle);
/*显示即时图像*/
imshow(WINDOW_NAME, tempImage);
if (waitKey(10) == 27)break; //等待10毫秒,在10毫秒内如果按了键盘并且按的是ascii码为27的键(ESC),则程序break。
}
return 0;
}
void on_MouseHandle(int event, int x, int y, int flag, void* param) {
Mat &image = *(cv::Mat*) param;
switch (event) {
case EVENT_MOUSEMOVE:
{
if (g_bDrawingBox) {
g_rectangle.width = x - g_rectangle.x;
g_rectangle.height = y - g_rectangle.y;
}
}break;
case EVENT_LBUTTONDOWN:
{
g_bDrawingBox = true;
g_rectangle = Rect(x, y, 0, 0); //记录起始点,
}break;
//构造函数 Rect(x,y,width,height),x, y 为左上角坐标, width, height 则为长和宽。
case EVENT_LBUTTONUP:
{
g_bDrawingBox = false;
/*
书上存在下面这段代码,但实际上DrawRectangle可对width、height为负的情况处理
Rect(x,y,width,height)中,x,y会绘制起点,DrawRectangle确定第二个点时,
直接将x/y与width/height进行算术运算,如(7,7,-5,-5)的起始点为(2,3),第二个
点为( 7+(-5),7+(-5) ),即(2,2),则tl为(2,2),br为(7,7)
书上这段代码是为了当width/height为负时(除了往右下角方向画,必然会有负值)
将绘制起点始终保持在矩阵的左上角(tl),且保持width/height均为正值,其实是不必要的。
如tempIamge没有进行此处理操作,仍然可以正常显示绘制轨迹
*/
/*if (g_rectangle.width < 0) {
g_rectangle.x = g_rectangle.x + g_rectangle.width;//找到鼠标松开的位置的横坐标
g_rectangle.width *= -1;
}
if (g_rectangle.height < 0) {
g_rectangle.y = g_rectangle.y + g_rectangle.height;//找到鼠标松开的位置的纵坐标
g_rectangle.height *= -1;
}*/
DrawRectangle(image, g_rectangle);
}break;
}
}
void DrawRectangle(cv::Mat &img, cv::Rect box) {
rectangle(img, box.tl(), box.br(), Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255)));
}//tl- TopLeft, br- BottomRight 左上角和右下角两个点可确定一个矩阵
/*基本图形的绘制*/
#include "stdafx.h"
#include <opencv2/opencv.hpp>
using namespace cv;
#define WINDOW_NAME "绘画框"
#define WINDOW_WIDTH 600
/* 椭圆 */
void DrawEllipse(Mat img, double angle) {
int thickness = 2;
int lineType = 5;
ellipse(img, Point(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2), Point(WINDOW_WIDTH / 4, WINDOW_WIDTH / 24),
angle, 0, 360, Scalar(255, 129, 0), thickness, lineType);
}
/* 实心圆 */
void DrawFilledCircle(Mat img, Point center) {
int thickness = -1;
int lineType = 8;
circle(img, center, WINDOW_WIDTH / 50, Scalar(0, 0, 255), thickness, lineType);
}
/* 多边形 */
void DrawPolygon(Mat img) {
int lineType = 8;
Point point[1][5];
point[0][0] = Point(WINDOW_WIDTH / 4, 1 * WINDOW_WIDTH / 2);
point[0][1] = Point(3*WINDOW_WIDTH / 4, 6 * WINDOW_WIDTH / 8);
point[0][2] = Point(WINDOW_WIDTH / 2, 7 * WINDOW_WIDTH / 8);
point[0][3] = Point(2*WINDOW_WIDTH / 3, 3 * WINDOW_WIDTH / 8);
point[0][4] = Point(WINDOW_WIDTH / 4, 1 * WINDOW_WIDTH / 2);
const Point* pot[1] = { point[0] };
int npt[] = { 5 };
fillPoly(img, pot, npt,1 , Scalar(255, 255, 0), lineType);
}
/* 画线 */
void DrawLine(Mat img, Point start, Point end) {
int thickness = 2;
int lineType = 8;
line(img, start, end, Scalar(0, 0, 0), thickness, lineType);
}
int main() {
namedWindow(WINDOW_NAME);
Point center(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2);
Point point(3 * WINDOW_WIDTH / 4, WINDOW_WIDTH / 2);
Mat image(WINDOW_WIDTH, WINDOW_WIDTH,CV_8UC3,Scalar(255,255,255));
DrawEllipse(image, 0);
DrawEllipse(image, 45);
DrawEllipse(image, 90);
DrawEllipse(image, -45);
DrawFilledCircle(image, center);
//DrawPolygon(image);
//DrawLine(image, center, point);
imshow(WINDOW_NAME,image );
waitKey(0);
return 0;
}