环境配置:opencv2.4.13 vs2015 Qt5.7.1
注意:
1、openCV自带的磨皮、美白效果只能进行参考,性能不高,才采用快速双边滤波
2、示例中openCV只用来打开了摄像头,可用系统自带api替代;
3、需要先编译jpeg.lib
处理步骤:
1:从摄像头抓取一帧;
2:利用libjpeg将IplImage转成jpeg;
3:快速双边滤波处理图像;
4:unsigned char *转QImage并显示;
性能参数:线程数=4 ,i5处理器, 640*480为30ms左右,fps可达30,效率非常高;
项目目的结构:
1、main.cpp
#include
#include
#include
#include
using namespace std;
#include "cameratest.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
CameraTest w;
w.show();
return a.exec();
}
2、cameratest.h cameratest.cpp cameratest.ui
#ifndef CAMERATEST_H
#define CAMERATEST_H
#include
#include "ui_cameratest.h"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include
#include
static float sigma_spatial = 0.05f;
static float sigma_range = 0.05f;
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#define _CRT_SECURE_NO_WARNINGS
#include
#include // 设置采集数据的间隔时间
#include
using namespace cv;
class CameraTest : public QMainWindow
{
Q_OBJECT
public:
CameraTest(QWidget *parent = 0);
~CameraTest();
private:
Ui::CameraTestClass ui;
private slots:
void openCamara(); // 打开摄像头
void readFarme(); // 读取当前帧信息
void closeCamara(); // 关闭摄像头。
void horizontalSliderChanged(int);
void horizontalSliderChanged2(int);
private:
QTimer *timer;
QImage *imag;
CvCapture *cam;// 视频获取结构, 用来作为视频获取函数的一个参数
IplImage *frame;//申请IplImage类型指针,就是申请内存空间来存放每一帧图像
};
#endif // CAMERATEST_H
#include "cameratest.h"
#include
#include
#include "stb_image.h"
#include "RBFilter_AVX2.h"
#include "jpeg-9\jpeglib.h"
#include "crbfilter.h"
#include "stb_image_write.h"
using namespace std;
class TestRunTimer
{
clock_t begTime;
public:
void start() { begTime = clock(); }
float elapsedTimeMS() { return float(clock() - begTime); }
};
unsigned char * testRunRecursiveBF_AVX2_mt(unsigned char * image, int len, int thread_count, bool multiThread = true)
{
int width, height, channel;
unsigned char * img = stbi_load_from_memory((stbi_uc*)image, len, &width, &height, &channel, 4);
if (!img)
{
return NULL;
}
channel = 4;
unsigned char * img_out;
if (multiThread)
{
CRBFilterAVX2 rbf_object;
bool success = rbf_object.initialize(width, height, thread_count, false);
if (!success)
{
delete[] img;
return nullptr;
}
rbf_object.setSigma(sigma_spatial, sigma_range);
int pitch = rbf_object.getOptimalPitch(width);
img_out = (unsigned char*)_aligned_malloc(pitch * height, 32);
unsigned char* buffer = (unsigned char*)_aligned_malloc(pitch * height, 32);
for (int y = 0; y < height; y++)
{
memcpy(buffer + y * pitch, img + y * width * 4, width * 4);
}
delete[] img;
img = buffer;
success = rbf_object.filter(img_out, img, width, height, pitch);
if (!success)
return nullptr;
}
else
{
CRBFilter rbf_object;
int pitch = rbf_object.getOptimalPitch(width);
img_out = (unsigned char*)_aligned_malloc(pitch * height, 32);
unsigned char* buffer = (unsigned char*)_aligned_malloc(pitch * height, 32);
for (int y = 0; y < height; y++)
{
memcpy(buffer + y * pitch, img + y * width * 4, width * 4);
}
delete[] img;
img = buffer;
rbf_object.CRB_Filter(img, img_out, width, height, pitch, sigma_spatial, sigma_range);
}
_aligned_free(img);
return img_out;
}
static bool jpegSave(const char* filename, unsigned char *outbuffer, unsigned long outlen)
{
FILE *f;
fopen_s(&f, filename, "wb");
if (!f)
return false;
size_t size = fwrite(outbuffer, (size_t)outlen, 1, f);
fclose(f);
if (size == 1)
return true;
return false;
}
/*********************************
********* IplImage转jpeg *********
**********************************/
static bool ipl2jpeg(IplImage *img, unsigned char **outbuffer, unsigned long outlen)
{
unsigned char *outdata = (uchar *)img->imageData;
struct jpeg_compress_struct cinfo = { 0 };
struct jpeg_error_mgr jerr;
JSAMPROW row_ptr[1];
int row_stride;
*outbuffer = NULL;
outlen = 0;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
cinfo.image_width = img->width;
cinfo.image_height = img->height;
cinfo.input_components = img->nChannels;
cinfo.in_color_space = JCS_RGB;
jpeg_mem_dest(&cinfo, outbuffer, &outlen);
jpeg_set_defaults(&cinfo);
jpeg_start_compress(&cinfo, TRUE);
row_stride = img->width * img->nChannels;
while (cinfo.next_scanline < cinfo.image_height)
{
row_ptr[0] = &outdata[cinfo.next_scanline * row_stride];
jpeg_write_scanlines(&cinfo, row_ptr, 1);
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
return true;
}
CameraTest::CameraTest(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
cam = NULL;
timer = new QTimer(this);
imag = new QImage(); // 初始化
/*信号和槽*/
connect(timer, SIGNAL(timeout()), this, SLOT(readFarme())); // 时间到,读取当前摄像头信息
connect(ui.open, SIGNAL(clicked()), this, SLOT(openCamara()));
connect(ui.closeCam, SIGNAL(clicked()), this, SLOT(closeCamara()));
connect(ui.horizontalSlider, SIGNAL(valueChanged(int)), this, SLOT(horizontalSliderChanged(int)));
connect(ui.horizontalSlider_2, SIGNAL(valueChanged(int)), this, SLOT(horizontalSliderChanged2(int)));
ui.horizontalSlider->setValue(5);
ui.horizontalSlider->setMaximum(10);
ui.horizontalSlider_2->setValue(5);
ui.horizontalSlider_2->setMaximum(10);
}
void CameraTest::horizontalSliderChanged(int value)
{
int a = ui.horizontalSlider->value();
sigma_spatial = 0.01*value;
}
void CameraTest::horizontalSliderChanged2(int value)
{
int a = ui.horizontalSlider_2->value();
sigma_range = 0.01*value;
}
CameraTest::~CameraTest()
{
}
void CameraTest::openCamara()
{
cam = cvCreateCameraCapture(0);//打开摄像头,从摄像头中获取视频
timer->start(30); // 开始计时,超时则发出timeout()信号 1024/30 == fps
}
//
//TestRunTimer timer;
//timer.start();
//cout << ", QImage image---time ms: " << timer.elapsedTimeMS();
/*********************************
********* 读取摄像头信息 ***********
**********************************/
void CameraTest::readFarme()
{
unsigned char * buffer;
unsigned long len;
frame = cvQueryFrame(cam);
ipl2jpeg(frame, &buffer, len);
unsigned char * outImg = testRunRecursiveBF_AVX2_mt(buffer, len, 1,true);
QImage image((const uchar*)outImg, frame->width, frame->height, QImage::Format_ARGB32);
ui.label->setPixmap(QPixmap::fromImage(image));
_aligned_free(outImg);
free(buffer);
}
/*******************************
***关闭摄像头,释放资源,必须释放***
********************************/
void CameraTest::closeCamara()
{
timer->stop(); // 停止读取数据。
cvReleaseCapture(&cam);//释放内存;
}
3、crbfilter.h crbfilter.cpp RBFilter_AVX2.h RBFilter_AVX2.cpp 参考:快速双边滤波处理算法:https://www.cnblogs.com/cpuimage/p/7629304.html
https://download.csdn.net/download/u013495598/11078766
也可以邮件至[email protected],发demo