在 OpenCV 中检测后将图像放置在矩形上
Place image on rectangle after detection in OpenCV
我目前正在开发一个 android 应用程序,用户可以在其中选择他们想要的衬衫,然后使用后置摄像头将其放在 body 之上。检测部分已完成并开始工作,下面是我到目前为止所做的代码。
nerds_thesis_clartips_OpencvClass.h //header 文件 nerds_thesis_clartips_OpencvClass.cpp
#include <jni.h>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
/* Header for class nerds_thesis_clartips_OpencvClass */
using namespace cv;
using namespace std;
#ifndef _Included_nerds_thesis_clartips_OpencvClass
#define _Included_nerds_thesis_clartips_OpencvClass
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: nerds_thesis_clartips_OpencvClass
* Method: humanDetection
* Signature: (J)V
*/
void detectHuman(Mat& frame);
JNIEXPORT void JNICALL Java_nerds_thesis_clartips_OpencvClass_humanDetection
(JNIEnv *, jclass, jlong);
#ifdef __cplusplus
}
#endif
#endif
nerds_thesis_clartips_OpencvClass.cpp //C++文件
#include "nerds_thesis_clartips_OpencvClass.h"
JNIEXPORT void JNICALL Java_nerds_thesis_clartips_OpencvClass_humanDetection (JNIEnv *, jclass, jlong addrRgba){
Mat& frame = *(Mat*)addrRgba;
detectHuman(frame);
}
void detectHuman(Mat& frame){
// assign xml file to a variable
String human_cascade_name = "/storage/emulated/0/data/haarcascade_upperbody.xml";
CascadeClassifier human_cascade;
// load xml file
if(!human_cascade.load( human_cascade_name ) ) { printf("--(!)Error loading\n"); return; };
std::vector<Rect> humans;
Mat frame_gray;
Mat original;
frame.copyTo(original);
//convert input to grayscale
cvtColor( frame, frame_gray, CV_BGR2GRAY );
//increase image contrast
equalizeHist( frame_gray, frame_gray);
//Detect Human
human_cascade.detectMultiScale( frame_gray, humans, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(100, 100) );
//for (int i=0; i<humans.size(); i++)
//rectangle(frame, Point(humans[i].x, humans[i].y), Point(humans[i].x+humans[i].width, humans[i].y+humans[i].height), Scalar(0,255,0));
Mat imageMask = imread("C:/Users/Requinala/AndroidStudioProjects/CLARTIPS/app/src/main/res/drawable/bluevelvet.png", 1);
// Draw the mask over all rectangles
for (size_t i = 0; i < humans.size(); i++){
Rect r = humans[i];
Mat humanROI = frame_gray( humans[i] ); //image of the upper body
int h_temp = humans[i].height; // storing original height
int x = humans[i].x;
int y = humans[i].y - h_temp*(-0.6); // y is increased by 0.6*h
int w = humans[i].width;
int h = h_temp; // height detected
rectangle(frame,Point (x,y),Point(x + w,y +h),Scalar(255,0,255),1,4,0);
/*int xx =0, yy =0;
// Just iterate in face region pixel by pixel
for(int x = humans[i].x; x < humans[i].x+humans[i].width; x++){
for (int y = humans[i].y; y < humans[i].y+humans[i].height; y++){
//Copy Mask to Original image If the 0 chan
//Proper condition is over all color channels
//if (imageMask.at(xx,yy)[0] < 10){
// Copy to original image on (y,x) places the pixel of xx,yy mask
humanROI.at(y,x)[0] = imageMask.at(xx,yy)[0];
humanROI.at(y,x)[1] = imageMask.at(xx,yy)[1];
humanROI.at(y,x)[2] = imageMask.at(xx,yy)[2];
//}
// Iterate in mask x
xx =xx+1;
}
// iterate next row of imageMask
xx = 0;
yy =yy+1;
}*/
}
}
但是,我遇到了错误:
没有匹配的成员函数来调用 'at'
我应该怎么办?任何 help/ideas 将不胜感激。
通过查看您的代码:
//if (imageMask.at(xx,yy)[0] < 10){
// Copy to original image on (y,x) places the pixel of xx,yy mask
humanROI.at(y,x)[0] = imageMask.at(xx,yy)[0];
humanROI.at(y,x)[1] = imageMask.at(xx,yy)[1];
humanROI.at(y,x)[2] = imageMask.at(xx,yy)[2];
//}
很容易发现问题。您缺少模板规范。
您可以将其更改为以下内容:
//if (imageMask.at(xx,yy)[0] < 10){
// Copy to original image on (y,x) places the pixel of xx,yy mask
humanROI.at<uchar>(y,x)[0] = imageMask.at<uchar>(xx,yy)[0];
humanROI.at<uchar>(y,x)[1] = imageMask.at<uchar>(xx,yy)[1];
humanROI.at<uchar>(y,x)[2] = imageMask.at<uchar>(xx,yy)[2];
//}
甚至更好:
//if (imageMask.at(xx,yy)[0] < 10){
// Copy to original image on (y,x) places the pixel of xx,yy mask
humanROI.at<Vec3b>(y,x) = imageMask.at<Vec3b>(xx,yy);
//}
这应该可以解决你的编译错误,但是 humanROI
是灰度的,你可以这样做:
Mat humanColorROI;
cvtColor( humanROI, humanColorROI, CV_GRAY2BGR );
得到一个3通道的灰度图像。这样它应该可以工作。
P.S.: 关于你检测到尸体后停止,可能是崩溃了,或者你只调用了一次这个函数?最好再发一个问题,让你得到更多会员的帮助,也让其他会员更快找到答案。
我目前正在开发一个 android 应用程序,用户可以在其中选择他们想要的衬衫,然后使用后置摄像头将其放在 body 之上。检测部分已完成并开始工作,下面是我到目前为止所做的代码。
nerds_thesis_clartips_OpencvClass.h //header 文件 nerds_thesis_clartips_OpencvClass.cpp
#include <jni.h>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
/* Header for class nerds_thesis_clartips_OpencvClass */
using namespace cv;
using namespace std;
#ifndef _Included_nerds_thesis_clartips_OpencvClass
#define _Included_nerds_thesis_clartips_OpencvClass
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: nerds_thesis_clartips_OpencvClass
* Method: humanDetection
* Signature: (J)V
*/
void detectHuman(Mat& frame);
JNIEXPORT void JNICALL Java_nerds_thesis_clartips_OpencvClass_humanDetection
(JNIEnv *, jclass, jlong);
#ifdef __cplusplus
}
#endif
#endif
nerds_thesis_clartips_OpencvClass.cpp //C++文件
#include "nerds_thesis_clartips_OpencvClass.h"
JNIEXPORT void JNICALL Java_nerds_thesis_clartips_OpencvClass_humanDetection (JNIEnv *, jclass, jlong addrRgba){
Mat& frame = *(Mat*)addrRgba;
detectHuman(frame);
}
void detectHuman(Mat& frame){
// assign xml file to a variable
String human_cascade_name = "/storage/emulated/0/data/haarcascade_upperbody.xml";
CascadeClassifier human_cascade;
// load xml file
if(!human_cascade.load( human_cascade_name ) ) { printf("--(!)Error loading\n"); return; };
std::vector<Rect> humans;
Mat frame_gray;
Mat original;
frame.copyTo(original);
//convert input to grayscale
cvtColor( frame, frame_gray, CV_BGR2GRAY );
//increase image contrast
equalizeHist( frame_gray, frame_gray);
//Detect Human
human_cascade.detectMultiScale( frame_gray, humans, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(100, 100) );
//for (int i=0; i<humans.size(); i++)
//rectangle(frame, Point(humans[i].x, humans[i].y), Point(humans[i].x+humans[i].width, humans[i].y+humans[i].height), Scalar(0,255,0));
Mat imageMask = imread("C:/Users/Requinala/AndroidStudioProjects/CLARTIPS/app/src/main/res/drawable/bluevelvet.png", 1);
// Draw the mask over all rectangles
for (size_t i = 0; i < humans.size(); i++){
Rect r = humans[i];
Mat humanROI = frame_gray( humans[i] ); //image of the upper body
int h_temp = humans[i].height; // storing original height
int x = humans[i].x;
int y = humans[i].y - h_temp*(-0.6); // y is increased by 0.6*h
int w = humans[i].width;
int h = h_temp; // height detected
rectangle(frame,Point (x,y),Point(x + w,y +h),Scalar(255,0,255),1,4,0);
/*int xx =0, yy =0;
// Just iterate in face region pixel by pixel
for(int x = humans[i].x; x < humans[i].x+humans[i].width; x++){
for (int y = humans[i].y; y < humans[i].y+humans[i].height; y++){
//Copy Mask to Original image If the 0 chan
//Proper condition is over all color channels
//if (imageMask.at(xx,yy)[0] < 10){
// Copy to original image on (y,x) places the pixel of xx,yy mask
humanROI.at(y,x)[0] = imageMask.at(xx,yy)[0];
humanROI.at(y,x)[1] = imageMask.at(xx,yy)[1];
humanROI.at(y,x)[2] = imageMask.at(xx,yy)[2];
//}
// Iterate in mask x
xx =xx+1;
}
// iterate next row of imageMask
xx = 0;
yy =yy+1;
}*/
}
}
但是,我遇到了错误: 没有匹配的成员函数来调用 'at' 我应该怎么办?任何 help/ideas 将不胜感激。
通过查看您的代码:
//if (imageMask.at(xx,yy)[0] < 10){
// Copy to original image on (y,x) places the pixel of xx,yy mask
humanROI.at(y,x)[0] = imageMask.at(xx,yy)[0];
humanROI.at(y,x)[1] = imageMask.at(xx,yy)[1];
humanROI.at(y,x)[2] = imageMask.at(xx,yy)[2];
//}
很容易发现问题。您缺少模板规范。
您可以将其更改为以下内容:
//if (imageMask.at(xx,yy)[0] < 10){
// Copy to original image on (y,x) places the pixel of xx,yy mask
humanROI.at<uchar>(y,x)[0] = imageMask.at<uchar>(xx,yy)[0];
humanROI.at<uchar>(y,x)[1] = imageMask.at<uchar>(xx,yy)[1];
humanROI.at<uchar>(y,x)[2] = imageMask.at<uchar>(xx,yy)[2];
//}
甚至更好:
//if (imageMask.at(xx,yy)[0] < 10){
// Copy to original image on (y,x) places the pixel of xx,yy mask
humanROI.at<Vec3b>(y,x) = imageMask.at<Vec3b>(xx,yy);
//}
这应该可以解决你的编译错误,但是 humanROI
是灰度的,你可以这样做:
Mat humanColorROI;
cvtColor( humanROI, humanColorROI, CV_GRAY2BGR );
得到一个3通道的灰度图像。这样它应该可以工作。
P.S.: 关于你检测到尸体后停止,可能是崩溃了,或者你只调用了一次这个函数?最好再发一个问题,让你得到更多会员的帮助,也让其他会员更快找到答案。