我正在使用ofxCV,ofxOpencv和ofxColorQuantizer开发OpenFrameworks项目。从技术上讲,该项目正在分析通过网络摄像头捕获的实时视频,并实时分析图像,以收集和输出当前帧中最突出的颜色。当生成最突出的颜色时,我使用当前帧和前一帧之间的像素差异来生成已更新的颜色,并使用视频帧的更新或移动区域来找出最突出的颜色。
使用像素差异生成彩色托盘的原因是因为我想解决用户走进视频帧的情况,我想尝试收集人物的颜色托盘,例如他们穿着什么。例如红色衬衫,蓝色裤子将放在托盘中,白色背景将被排除在外。
我在Javascript和canvas方面有很强的背景,但对OpenFrameworks和C ++来说还是比较新的,这就是为什么我认为我遇到了上述问题的障碍。
与OpenFrameworks一起,我使用ofxCV,ofxOpencv和ofxColorQuantizer作为此安装的工具。我正在拍摄网络摄影图像,而不是使用cv:Mat,而不是在网络摄像头图像上使用两次缩写,然后是垫子的absdiff,而不是试图将垫子传递到ofxColorQuantizer。这就是我认为我遇到问题的地方 - 我不认为ofxColorQuantizer喜欢我尝试使用的图像的mat格式。我尝试过寻找不同的图片格式来尝试转换图片来解决这个问题,但我还没有能够解决问题。
为了提高效率,我希望在较小的图像上进行色差和颜色突出计算(在我缩小图像之后)并在屏幕上显示完整的图像,生成的调色板显示在左下角比如在ofxColorQuantizer中的例子。
我认为可能还有其他方法可以加快代码速度,但目前我正试图让应用程序的这一部分先运行。
我的main.cpp设置如下:
#include "ofMain.h"
#include "ofApp.h"
#include "ofAppGlutWindow.h"
//========================================================================
int main( ){
ofAppGlutWindow window;
ofSetupOpenGL(&window, 1024,768, OF_WINDOW); // <-------- setup the GL context
// ofSetupOpenGL(1024,768,OF_WINDOW); // <-------- setup the GL context
// this kicks off the running of my app
// can be OF_WINDOW or OF_FULLSCREEN
// pass in width and height too:
ofRunApp(new ofApp());
}
我的ofApp.h文件如下:
#pragma once
#include "ofMain.h"
#include "ofxOpenCv.h"
#include "ofxCv.h"
#include "ofxColorQuantizer.h"
class ofApp : public ofBaseApp{
public:
void setup();
void update();
void draw();
ofVideoGrabber cam;
ofPixels previous;
ofImage diff;
void kMeansTest();
ofImage image;
ofImage img;
cv::Mat matA, matB;
ofImage diffCopy;
ofImage outputImage;
ofxCv::RunningBackground background;
ofxColorQuantizer colorQuantizer;
// a scalar is like an ofVec4f but normally used for storing color information
cv::Scalar diffMean;
};
最后我的ofApp.cpp如下:
#include "ofApp.h"
using namespace ofxCv;
using namespace cv;
//--------------------------------------------------------------
void ofApp::setup(){
ofSetVerticalSync(true);
cam.initGrabber(320, 240);
// get our colors
colorQuantizer.setNumColors(3);
// resize the window to match the image
// ofSetWindowShape(image.getWidth(), image.getHeight());
ofSetWindowShape(800, 600);
// imitate() will set up previous and diff
// so they have the same size and type as cam
imitate(previous, cam);
imitate(diff, cam);
imitate(previous, outputImage);
imitate(diff, outputImage);
}
//--------------------------------------------------------------
void ofApp::update(){
cam.update();
if(cam.isFrameNew()) {
matA = ofxCv::toCv(cam.getPixelsRef());
ofxCv::pyrDown(matA, matB);
ofxCv::pyrDown(matB, matA);
ofxCv::medianBlur(matA, 3);
ofxCv::toOf(matA, outputImage);
// take the absolute difference of prev and cam and save it inside diff
absdiff(previous, outputImage, diff);
}
}
//--------------------------------------------------------------
void ofApp::draw(){
// If the image is ready to draw, then draw it
if(outputImage.isAllocated()) {
outputImage.update();
outputImage.draw(0, 0, ofGetWidth(), ofGetHeight());
}
ofBackground(100,100,100);
ofSetColor(255);
ofImage diffCopy;
diffCopy = diff;
diffCopy.resize(diffCopy.getWidth()/2, diffCopy.getHeight()/2);
// there is some sort of bug / issue going on here...
// prevent the app from compiling
// comment out to run and see blank page
colorQuantizer.quantize(diffCopy.getPixelsRef());
ofLog() << "the number is " << outputImage.getHeight();
ofLog() << "the number is " << diffCopy.getHeight();
ofSetColor(255);
img.update();
// cam.draw(0, 0, 800, 600);
outputImage.draw(0, 0, 800, 600);
// colorQuantizer.draw(ofPoint(0, cam.getHeight()-20));
colorQuantizer.draw(ofPoint(0, 600-20));
// use the [] operator to get elements from a Scalar
float diffRed = diffMean[0];
float diffGreen = diffMean[1];
float diffBlue = diffMean[2];
ofSetColor(255, 0, 0);
ofRect(0, 0, diffRed, 10);
ofSetColor(0, 255, 0);
ofRect(0, 15, diffGreen, 10);
ofSetColor(0, 0, 255);
ofRect(0, 30, diffBlue, 10);
}
//--------------------------------------------------------------
void ofApp::kMeansTest(){
cv::Mat samples = (cv::Mat_<float>(8, 1) << 31 , 2 , 10 , 11 , 25 , 27, 2, 1);
cv::Mat labels;
// double kmeans(const Mat& samples, int clusterCount, Mat& labels,
cv::TermCriteria termcrit;
int attempts, flags;
cv::Mat centers;
double compactness = cv::kmeans(samples, 3, labels, cv::TermCriteria(), 2, cv::KMEANS_PP_CENTERS, centers);
cout<<"labels:"<<endl;
for(int i = 0; i < labels.rows; ++i)
{
cout<<labels.at<int>(0, i)<<endl;
}
cout<<"\ncenters:"<<endl;
for(int i = 0; i < centers.rows; ++i)
{
cout<<centers.at<float>(0, i)<<endl;
}
cout<<"\ncompactness: "<<compactness<<endl;
}
提前为我的代码状态道歉 - 它已经迟到了,我试图完成这项工作。
我的问题是openFrameworks用于抓取网络摄像头图像的图像格式是什么,openCV期望的图像格式是什么,我应该使用什么来从mat图像切换回ofImage,是否有办法获取getPixelsRef从mat图像?
我认为我有错误的代码区域是以下逻辑。
matA = ofxCv::toCv(cam.getPixelsRef());
ofxCv::pyrDown(matA, matB);
我认为更改框架的图像格式或像素格式ofxCv::toOf(matA, outputImage);
,colorQuantizer.quantize(diffCopy.getPixelsRef());
以尝试生成调色板以进行像素更改。 colorQuantizer类和函数调用给出了一个错误,它使用[ error ] ofTexture: allocate(): ofTextureData has 0 width and/or height: 0x0
EXC_BAD_ACCESS
最后,是否有替代原因导致exc_bad_access线程错误而不是图像格式化?作为c ++的新手,我只是在猜测和摆脱我认为问题的根本原因的本能。
非常感谢。