i have app has pull frames video, transform 1 little, transform 1 lot, , simultaneously display them in gui. in worker thread, there's opencv loop:
while(1) { cv::videocapture kalibrowanyplik; kalibrowanyplik.open(kalibracja.tostdstring()); //open file url int maxframes = kalibrowanyplik.get(cv_cap_prop_frame_count); for(int i=0; i<maxframes; i++) //i thought crashed when finished reading first time around { cv::mat frame; cv::mat gray; cv::mat color; kalibrowanyplik.read(frame); cv::cvtcolor(frame, gray, cv_bgr2gray); cv::cvtcolor(frame, color, cv_bgr2rgb); qimage image((uchar*)color.data, color.cols, color.rows,qimage::format_rgb888); qimage processedimage((uchar*)gray.data, gray.cols, gray.rows,qimage::format_indexed8); emit progresschanged(image, processedimage); qthread::msleep(50); } }
and how frames placed in gui
void mainwindow::onprogresschagned(qimage image, qimage processedimage) { qpixmap processed = qpixmap::fromimage(processedimage); processed = processed.scaledtoheight(379); ui->labelhsv->clear(); ui->labelhsv->setpixmap(processed); qpixmap original = qpixmap::fromimage(image); //debug points sigsegv here original = original.scaledtoheight(379); ui->labelkalibracja->clear(); ui->labelkalibracja->setpixmap(original); }
the rgb image crashes, grayscale image never crashes (tested). why rgb image crashing?
edit: i've discovered if change msleep(50)
msleep(100)
executes perfectly. don't want that. need @ least 25 frames per second, 10 not acceptable... why cause sigsegv
standard issue. problem memory management! see other answer. in comments there is link.
so in code qimage
doesn't copy , doesn't take ownership of memory of matrix. , later on when matrix destroyed , qimage
tries access memory (qimage
copied creating shallow copy) have segfault.
here code form this link (i've tweak bit), reason site has administration issues (some quota exceeded), why i'm pasting here.
inline qimage cvmattoqimage( const cv::mat &inmat ) { switch ( inmat.type() ) { // 8-bit, 4 channel case cv_8uc4: { qimage image( inmat.data, inmat.cols, inmat.rows, inmat.step, qimage::format_rgb32 ); qimage copy(image); copy.bits(); //enforce deep copy return copy; } // 8-bit, 3 channel case cv_8uc3: { qimage image( inmat.data, inmat.cols, inmat.rows, inmat.step, qimage::format_rgb888 ); return image.rgbswapped(); } // 8-bit, 1 channel case cv_8uc1: { static qvector<qrgb> scolortable; // create our color table once if ( scolortable.isempty() ) { ( int = 0; < 256; ++i ) scolortable.push_back( qrgb( i, i, ) ); } qimage image( inmat.data, inmat.cols, inmat.rows, inmat.step, qimage::format_indexed8 ); image.setcolortable( scolortable ); qimage copy(image); copy.bits(); //enforce deep copy return copy; } default: qwarning() << "asm::cvmattoqimage() - cv::mat image type not handled in switch:" << inmat.type(); break; } return qimage(); }
your code should utilize functions that:
while(1) { cv::videocapture kalibrowanyplik; kalibrowanyplik.open(kalibracja.tostdstring()); //open file url int maxframes = kalibrowanyplik.get(cv_cap_prop_frame_count); for(int i=0; i<maxframes; i++) //i thought crashed when finished reading first time around { cv::mat frame; cv::mat gray; kalibrowanyplik.read(frame); cv::cvtcolor(frame, gray, cv_bgr2gray); qimage image(cvmattoqimage(frame)); qimage processedimage(cvmattoqimage(gray)); emit progresschanged(image, processedimage); qthread::msleep(10); // bad see comments below } }
use of msleep
in 95% cases bad! remove loop , create slot invoked signal qtimer
.
Comments
Post a Comment