int c= waitKey(15);的理解和使用

这段代码展示了如何使用OpenCV的waitKey函数在显示图片窗口后等待用户交互。waitKey函数可以设置超时时间,当用户按下任意键或者超过指定时间后,程序将退出循环。示例中分别演示了无限等待、定时等待以及特定按键触发的情况。
#include "pch.h"
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char *argv[])
{
    int d=0;
    char ad[200]={0};
    //char name;
    //从电脑摄像头读入
    VideoCapture capture(0);
    //Mat edges;
    //waitKey(2000);
    //循环显示每一帧
    Mat frame;
    while(1)
    {
        capture>>frame;//读取当前帧
        imshow("读取视频",frame);
 
		int c= waitKey(15);
        int a=waitKey(10);//延时30ms
        if(a=='e'||cvGetWindowHandle("读取视频")==nullptr)
            break;
        else if(c=='c')
        {
           sprintf_s(ad, "E:\\tb\\project\\tb2\\face_tb\\face_tb\\face_tb\\face_tb\\output_face\\%d.jpg", ++d);
           imwrite(ad, frame );
           cout<<"get "<<d<<"  picture "<<endl;
        }
    } 
    return 0;
}
 
waitkey只是获取一个键

#include <openc

#include<iostream> #include<atlimage.h> #include<cmath> #include<vector> using namespace std; int main() { LPCTSTR srcFilePath = _T("1.jpg"), destFilePath = _T("11.jpg"); CImage srcImage; srcImage.Load(srcFilePath); int width = srcImage.GetWidth(); int height = srcImage.GetHeight(); int bpp = srcImage.GetBPP(); int pitch = srcImage.GetPitch(); BYTE* pData = (BYTE*)srcImage.GetBits(); // RGB 转灰度 for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // 计算当前像素偏移 int offset = pitch * y + x * bpp / 8; BYTE b = pData[offset + 0]; BYTE g = pData[offset + 1]; BYTE r = pData[offset + 2]; BYTE gray = (BYTE)round(r * 0.299 + g * 0.587 + b * 0.114); pData[offset + 0] = gray; pData[offset + 1] = gray; pData[offset + 2] = gray; } } // 2. Laplacian 边缘检测(创建临时灰度缓冲区,避免覆盖原数据) vector<BYTE> grayBuffer(width * height); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int offset = pitch * y + x * bpp / 8; grayBuffer[y * width + x] = pData[offset]; } } // 应用 Laplacian 卷积 vector<BYTE> edgeBuffer(width * height, 0); for (int y = 1; y < height - 1; y++) { for (int x = 1; x < width - 1; x++) { int sum = 0; // 遍历 3x3 核 for (int ky = -1; ky <= 1; ky++) { for (int kx = -1; kx <= 1; kx++) { int pixel = grayBuffer[(y + ky) * width + (x + kx)]; sum += pixel * laplacianKernel[ky + 1][kx + 1]; } } // 截断到 [0, 255] edgeBuffer[y * width + x] = (BYTE)max(0, min(255, sum)); } } // 将边缘检测结果写回图像(转为单通道或 RGB 叠加,这里用单通道演示) // 若要 RGB 三通道相同,可循环赋值 R/G/B for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int offset = pitch * y + x * bpp / 8; pData[offset + 0] = edgeBuffer[y * width + x]; pData[offset + 1] = edgeBuffer[y * width + x]; pData[offset + 2] = edgeBuffer[y * width + x]; } } srcImage.Save(destFilePath); return 0; }
07-19
#include <opencv2/opencv.hpp> #include using namespace std; using namespace cv; #define WINDOW_NAME “【程序窗口1】” //全局变量的声明 Mat g_maskImage, g_srcImage; Point prevPt(-1,-1); bool g_bDrawingBox = false; //全局函数的声明 static void ShowHelpText() ; static void on_Mouse( int event, int x, int y, int flags, void* ); int main( int argc, char** argv ){ //【1】载入原图并显示,初始化掩膜灰度图 g_srcImage = imread(“2.jpg”, 1); imshow( WINDOW_NAME, g_srcImage ); Mat srcImage, grayImage; g_srcImage.copyTo(srcImage) ; cvtColor(g_srcImage, g_maskImage, COLOR_BGR2GRAY); cvtColor (g_maskImage, grayImage, COLOR_GRAY2BGR); g_maskImage = Scalar::all (0); //【2】设置鼠标回调函数 setMouseCallback( WINDOW_NAME, on_Mouse, 0 ); //【3】轮询按键,进行处理 while(1){ //获取键值 int c = waitKey(0); //若按键键值为 ESC 时,退出 if( (char)c == 27 ) break; //按键键值为2时,恢复源图 if( (char)c ==‘2’){ g_maskImage = Scalar::all (0); srcImage.copyTo(g_srcImage); imshow( “image”, g_srcImage ); } //若检测到按键值为 1或者空格,则进行处理 if( (char)c ‘1’ || (char)c’ '){ //定义一些参数 int i, j, compCount = 0; vector<vector > contours; vector hierarchy; //寻找轮廓 findContours (g_maskImage, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE); //轮廓为空时的处理 if( contours.empty() ) continue; //复制掩膜 Mat maskImage (g_maskImage.size(), CV_32S); maskImage = Scalar::all(0); //循环绘制出轮廓 for (int index = 0; index >= 0; index++) { drawContours(maskImage,contours,index,Scalar::all(compCount+1),-1,8,hierarchy,INT_MAX); } //compCount为零时的处理 if( compCount ==0)continue; //生成随机颜色 vector<Vec3b> colorTab; for(i=0; i< compCount; i++ ){ int b = theRNG().uniform(0, 255); int g = theRNG().uniform(0, 255); int r = theRNG().uniform(0, 255); colorTab.push_back (Vec3b ((uchar)b, (uchar)g, (uchar)r)); } //计算处理时间并输出到窗口中 double dTime = (double)getTickCount(); watershed( srcImage, maskImage ); dTime = (double)getTickCount() - dTime; printf("\t处理时间= %gms\n",dTime*1000./getTickFrequency()); //双层循环,将分水岭图像遍历存入 watershedImage 中 Mat watershedImage (maskImage.size(), CV_8UC3); for ( i = 0; i < maskImage.rows; i++ ) for( j = 0; j < maskImage.cols; j++ ){ int index = maskImage.at<int>(i, j) ; if( index ==-1 ) watershedImage.at<Vec3b> (i, j) =Vec3b(255, 255, 255); else if( index <=0 || index > compCount ) watershedImage.at<Vec3b>(i, j) = Vec3b(0, 0,0); else watershedImage.at<Vec3b>(i, j) = colorTab[index -1]; } //混合灰度图分水岭效果图并显示最终的窗口 watershedImage = watershedImage*0.5 + grayImage*0.5; imshow ( "watershed transform", watershedImage ); } } return 0; } //鼠标消息回调函数 static void on_Mouse( int event, int x, int y, int flags, void* ){ //处理鼠标不在窗口中的情况 if(x<0 || x >= g_srcImage.cols || y < 0 || y >= g_srcImage.rows ) return; //处理鼠标左键相关消息 if( event == EVENT_LBUTTONUP || !(flags & EVENT_FLAG_LBUTTON) ) prevPt = Point(-1, -1) ; else if( event == EVENT_LBUTTONDOWN ) prevPt = Point(x, y); //鼠标左键按下并移动,绘制出白色线条 else if( event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON)||g_bDrawingBox){ Point pt(x, y); if( prevPt.x < 0 ) prevPt = pt; line( g_maskImage, prevPt, pt, Scalar::all(255), 5, 8, 0 ); line( g_srcImage, prevPt, pt, Scalar::all(255), 5, 8, 0 ); prevPt =pt; imshow(WINDOW_NAME, g_srcImage); } }使用g_bDrawingBox
最新发布
07-20
#include <opencv2/opencv.hpp> #include <cmath> #include <complex> #include <vector> #include <iostream> using namespace cv; using namespace std; // 位反转函数(用于蝶形运算准备) int bitReverse(int num, int log2n) { int result = 0; for (int i = 0; i < log2n; ++i) { if (num & (1 << i)) result |= 1 << (log2n - 1 - i); } return result; } // 1D FFT实现(基2-FFT蝶形运算) void fft(vector<complex<float>>& data, bool inverse = false) { const int n = data.size(); const int log2n = static_cast<int>(log2(n)); // 位反转重排 vector<complex<float>> temp(n); for (int i = 0; i < n; ++i) { int rev = bitReverse(i, log2n); temp[i] = data[rev]; } // 蝶形运算 for (int s = 1; s <= log2n; ++s) { int m = 1 << s; // 当前处理块大小 float ang = 2 * CV_PI / m * (inverse ? 1 : -1); complex<float> wm(cos(ang), sin(ang)); for (int k = 0; k < n; k += m) { complex<float> w(1.0f); for (int j = 0; j < m / 2; ++j) { complex<float> t = w * temp[k + j + m / 2]; complex<float> u = temp[k + j]; temp[k + j] = u + t; temp[k + j + m / 2] = u - t; w *= wm; } } } // 逆变换缩放 if (inverse) { for (auto& x : temp) x /= n; } data = temp; } // 2D FFT实现 void fft2d(Mat& complexImage, bool inverse = false) { int rows = complexImage.rows; int cols = complexImage.cols; // 行变换 for (int y = 0; y < rows; ++y) { vector<complex<float>> rowData; for (int x = 0; x < cols; ++x) { rowData.push_back(complexImage.at<Vec2f>(y, x).val[0] + complexImage.at<Vec2f>(y, x).val[1] * 1if); } fft(rowData, inverse); for (int x = 0; x < cols; ++x) { complexImage.at<Vec2f>(y, x) = Vec2f(rowData[x].real(), rowData[x].imag()); } } // 列变换 for (int x = 0; x < cols; ++x) { vector<complex<float>> colData; for (int y = 0; y < rows; ++y) { colData.push_back(complexImage.at<Vec2f>(y, x).val[0] + complexImage.at<Vec2f>(y, x).val[1] * 1if); } fft(colData, inverse); for (int y = 0; y < rows; ++y) { complexImage.at<Vec2f>(y, x) = Vec2f(colData[y].real(), colData[y].imag()); } } } // 频域中心化 (fftshift) void fftShift(Mat& mag) { int cx = mag.cols / 2; int cy = mag.rows / 2; Mat q0(mag, Rect(0, 0, cx, cy)); Mat q1(mag, Rect(cx, 0, cx, cy)); Mat q2(mag, Rect(0, cy, cx, cy)); Mat q3(mag, Rect(cx, cy, cx, cy)); Mat tmp; q0.copyTo(tmp); q3.copyTo(q0); tmp.copyTo(q3); q1.copyTo(tmp); q2.copyTo(q1); tmp.copyTo(q2); } // 计算MSE double calculateMSE(const Mat& img1, const Mat& img2) { if (img1.size() != img2.size() || img1.type() != img2.type()) { cerr << "Images must have same size and type" << endl; return -1; } Mat diff; absdiff(img1, img2, diff); diff = diff.mul(diff); Scalar s = sum(diff); return s[0] / (img1.total() * img1.channels()); } // 计算PSNR double calculatePSNR(const Mat& img1, const Mat& img2) { double mse = calculateMSE(img1, img2); if (mse <= 1e-10) return 100; // 避免除以0 return 10.0 * log10((255.0 * 255.0) / mse); } // 创建高斯低通滤波器掩膜 Mat createGaussianLowPassFilter(Size size, double sigma) { Mat mask = Mat::zeros(size, CV_32F); Point center(size.width / 2, size.height / 2); for (int y = 0; y < size.height; y++) { for (int x = 0; x < size.width; x++) { double d = sqrt(pow(x - center.x, 2) + pow(y - center.y, 2)); mask.at<float>(y, x) = exp(-(d * d) / (2 * sigma * sigma)); } } return mask; } int main() { // 读取灰度图像 Mat img = imread("input.jpg", IMREAD_GRAYSCALE); if (img.empty()) { cerr << "Could not read image" << endl; return -1; } // 调整大小为2的幂次(FFT要求) int newRows = pow(2, ceil(log2(img.rows))); int newCols = pow(2, ceil(log2(img.cols))); resize(img, img, Size(newCols, newRows)); // 转换为浮点型并归一化 Mat floatImg; img.convertTo(floatImg, CV_32F, 1.0 / 255.0); // 准备复数矩阵(实部=图像,虚部=0) Mat planes[] = { Mat_<float>(floatImg), Mat::zeros(floatImg.size(), CV_32F) }; Mat complexImg; merge(planes, 2, complexImg); // ===== 执行FFT ===== fft2d(complexImg); // 分离实部虚部 split(complexImg, planes); // 计算幅度谱 (log scale) Mat mag; magnitude(planes[0], planes[1], mag); mag += Scalar::all(1); // 避免log(0) log(mag, mag); normalize(mag, mag, 0, 1, NORM_MINMAX); // 频域中心化 fftShift(mag); // 显示幅度谱 imshow("Frequency Spectrum", mag); imwrite("spectrum.jpg", mag * 255); waitKey(0); // ===== 重建原始图像 (IFFT) ===== fft2d(complexImg, true); // 逆变换 // 获取实部作为重建图像 split(complexImg, planes); Mat reconstructed; normalize(planes[0], reconstructed, 0, 1, NORM_MINMAX); // 显示重建图像 imshow("Reconstructed Image", reconstructed); imwrite("reconstructed.jpg", reconstructed * 255); // 计算重建MSE/PSNR double mseOriginal = calculateMSE(floatImg, reconstructed); double psnrOriginal = calculatePSNR(floatImg, reconstructed * 255); cout << "MSE (Original): " << mseOriginal << endl; cout << "PSNR (Original): " << psnrOriginal << " dB" << endl; // =====高斯低通滤波处理 ===== // 创建高斯低通滤波器(截止频率=图像尺寸的15%) double sigma = min(img.rows, img.cols) * 0.08; // 调整截止频率参数 Mat lpfMask = createGaussianLowPassFilter(complexImg.size(), sigma); // 应用滤波器(在频域中心化状态) fftShift(mag); Mat filteredPlanes[] = { planes[0].mul(lpfMask), planes[1].mul(lpfMask) }; Mat filteredComplex; merge(filteredPlanes, 2, filteredComplex); // 逆变换得到滤波后图像 fft2d(filteredComplex, true); split(filteredComplex, filteredPlanes); Mat filteredImg; normalize(filteredPlanes[0], filteredImg, 0, 1, NORM_MINMAX); // 显示滤波后图像 imshow("高斯Low-Pass Filtered", filteredImg); imwrite("filtered.jpg", filteredImg * 255); // 计算滤波后PSNR double mseFiltered = calculateMSE(floatImg, filteredImg); double psnrFiltered = calculatePSNR(floatImg, filteredImg * 255); cout << "MSE (Filtered): " << mseFiltered << endl; cout << "PSNR (Filtered): " << psnrFiltered << " dB" << endl; waitKey(0); return 0; }
06-05
#include <opencv2/opencv.hpp> #include <cmath> #include <complex> #include <vector> #include <iostream> using namespace cv; using namespace std; // 位反转函数(用于蝶形运算准备) int bitReverse(int num, int log2n) { int result = 0; for (int i = 0; i < log2n; ++i) { if (num & (1 << i)) result |= 1 << (log2n - 1 - i); } return result; } // 1D FFT实现(基2-FFT蝶形运算) void fft(vector<complex<float>>& data, bool inverse = false) { const int n = data.size(); const int log2n = static_cast<int>(log2(n)); // 位反转重排 vector<complex<float>> temp(n); for (int i = 0; i < n; ++i) { int rev = bitReverse(i, log2n); temp[i] = data[rev]; } // 蝶形运算 for (int s = 1; s <= log2n; ++s) { int m = 1 << s; // 当前处理块大小 float ang = 2 * CV_PI / m * (inverse ? 1 : -1); complex<float> wm(cos(ang), sin(ang)); for (int k = 0; k < n; k += m) { complex<float> w(1.0f); for (int j = 0; j < m / 2; ++j) { complex<float> t = w * temp[k + j + m / 2]; complex<float> u = temp[k + j]; temp[k + j] = u + t; temp[k + j + m / 2] = u - t; w *= wm; } } } // 逆变换缩放 if (inverse) { for (auto& x : temp) x /= n; } data = temp; } // 2D FFT实现 void fft2d(Mat& complexImage, bool inverse = false) { int rows = complexImage.rows; int cols = complexImage.cols; // 行变换 for (int y = 0; y < rows; ++y) { vector<complex<float>> rowData; for (int x = 0; x < cols; ++x) { rowData.push_back(complexImage.at<Vec2f>(y, x).val[0] + complexImage.at<Vec2f>(y, x).val[1] * 1if); } fft(rowData, inverse); for (int x = 0; x < cols; ++x) { complexImage.at<Vec2f>(y, x) = Vec2f(rowData[x].real(), rowData[x].imag()); } } // 列变换 for (int x = 0; x < cols; ++x) { vector<complex<float>> colData; for (int y = 0; y < rows; ++y) { colData.push_back(complexImage.at<Vec2f>(y, x).val[0] + complexImage.at<Vec2f>(y, x).val[1] * 1if); } fft(colData, inverse); for (int y = 0; y < rows; ++y) { complexImage.at<Vec2f>(y, x) = Vec2f(colData[y].real(), colData[y].imag()); } } } // 频域中心化 (fftshift) void fftShift(Mat& mag) { int cx = mag.cols / 2; int cy = mag.rows / 2; Mat q0(mag, Rect(0, 0, cx, cy)); Mat q1(mag, Rect(cx, 0, cx, cy)); Mat q2(mag, Rect(0, cy, cx, cy)); Mat q3(mag, Rect(cx, cy, cx, cy)); Mat tmp; q0.copyTo(tmp); q3.copyTo(q0); tmp.copyTo(q3); q1.copyTo(tmp); q2.copyTo(q1); tmp.copyTo(q2); } // 计算MSE double calculateMSE(const Mat& img1, const Mat& img2) { if (img1.size() != img2.size() || img1.type() != img2.type()) { cerr << "Images must have same size and type" << endl; return -1; } Mat diff; absdiff(img1, img2, diff); diff = diff.mul(diff); Scalar s = sum(diff); return s[0] / (img1.total() * img1.channels()); } // 计算PSNR double calculatePSNR(const Mat& img1, const Mat& img2) { double mse = calculateMSE(img1, img2); if (mse <= 1e-10) return 100; // 避免除以0 return 10.0 * log10((255.0 * 255.0) / mse); } // 创建低通滤波器掩膜 Mat createLowPassFilter(Size size, double D0) { Mat mask = Mat::zeros(size, CV_32F); Point center(size.width / 2, size.height / 2); for (int y = 0; y < size.height; y++) { for (int x = 0; x < size.width; x++) { double d = sqrt(pow(x - center.x, 2) + pow(y - center.y, 2)); if (d <= D0) { mask.at<float>(y, x) = 1.0f; } } } return mask; } int main() { // 读取灰度图像 Mat img = imread("input.jpg", IMREAD_GRAYSCALE); if (img.empty()) { cerr << "Could not read image" << endl; return -1; } // 调整大小为2的幂次(FFT要求) int newRows = pow(2, ceil(log2(img.rows))); int newCols = pow(2, ceil(log2(img.cols))); resize(img, img, Size(newCols, newRows)); // 转换为浮点型并归一化 Mat floatImg; img.convertTo(floatImg, CV_32F, 1.0 / 255.0); // 准备复数矩阵(实部=图像,虚部=0) Mat planes[] = { Mat_<float>(floatImg), Mat::zeros(floatImg.size(), CV_32F) }; Mat complexImg; merge(planes, 2, complexImg); // ===== 执行FFT ===== fft2d(complexImg); // 分离实部虚部 split(complexImg, planes); // 计算幅度谱 (log scale) Mat mag; magnitude(planes[0], planes[1], mag); mag += Scalar::all(1); // 避免log(0) log(mag, mag); normalize(mag, mag, 0, 1, NORM_MINMAX); // 频域中心化 fftShift(mag); // 显示幅度谱 imshow("Frequency Spectrum", mag); imwrite("spectrum.jpg", mag * 255); waitKey(0); // ===== 重建原始图像 (IFFT) ===== fft2d(complexImg, true); // 逆变换 // 获取实部作为重建图像 split(complexImg, planes); Mat reconstructed; normalize(planes[0], reconstructed, 0, 1, NORM_MINMAX); // 显示重建图像 imshow("Reconstructed Image", reconstructed); imwrite("reconstructed.jpg", reconstructed * 255); // 计算重建MSE/PSNR double mseOriginal = calculateMSE(floatImg, reconstructed); double psnrOriginal = calculatePSNR(floatImg, reconstructed * 255); cout << "MSE (Original): " << mseOriginal << endl; cout << "PSNR (Original): " << psnrOriginal << " dB" << endl; // ===== 低通滤波处理 ===== // 创建低通滤波器(截止频率=图像尺寸的15%) double D0 = min(img.rows, img.cols) * 0.15; Mat lpfMask = createLowPassFilter(complexImg.size(), D0); // 应用滤波器(在频域中心化状态) fftShift(mag); // 确保频域在中心 Mat filteredPlanes[] = { planes[0].mul(lpfMask), planes[1].mul(lpfMask) }; Mat filteredComplex; merge(filteredPlanes, 2, filteredComplex); // 逆变换得到滤波后图像 fft2d(filteredComplex, true); split(filteredComplex, filteredPlanes); Mat filteredImg; normalize(filteredPlanes[0], filteredImg, 0, 1, NORM_MINMAX); // 显示滤波后图像 imshow("Low-Pass Filtered", filteredImg); imwrite("filtered.jpg", filteredImg * 255); // 计算滤波后PSNR double mseFiltered = calculateMSE(floatImg, filteredImg); double psnrFiltered = calculatePSNR(floatImg, filteredImg * 255); cout << "MSE (Filtered): " << mseFiltered << endl; cout << "PSNR (Filtered): " << psnrFiltered << " dB" << endl; waitKey(0); return 0; } 将低通滤波器改为高斯滤波器并给出完整代码
06-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值