How to find specified number keypoints in mask
Cross post here
ORB is very fast, but it always too few points,which make me awkward. So I have made a such mask
I want to find 10 keypoints in every white rectangle by ORB. But as the documentation here. The first argument just mean:
The maximum number of features to retain.
This is my current method
//OpenCV 3.3.1 project
#include<opencv.hpp>
using namespace std;
using namespace cv;
Mat highlight(Mat, Mat);
int main() {
Mat emptyImg = imread("test.jpg", 0);
Mat test = emptyImg.clone();
Mat mask(5, 5, CV_8UC1, Scalar(0));
for (int i = 0; i < mask.rows; i++) {
uchar* data = mask.ptr<uchar>(i);
for (int j = 0; j < mask.cols; j++)
if ((i + j) % 2 == 0)
data[j] = 255;
}
resize(mask, mask, emptyImg.size(), 0, 0, INTER_NEAREST);
Mat labels, stats, centroids;
int nmask = connectedComponentsWithStats(mask, labels, stats, centroids, 4, CV_16U);
stats.convertTo(stats, CV_8U);
vector<Mat> rects;
for (int i = 1; i < nmask; i++) {
uchar* data = stats.ptr<uchar>(i);
Mat temImg = Mat(mask.size(), CV_8UC1, Scalar(0));
rectangle(temImg, Rect(data[0], data[1], data[2], data[3]), Scalar(255), FILLED);
rects.push_back(temImg);
}
Ptr<ORB> detector = ORB::create(10);
vector<KeyPoint> keypoints_empty;
for (int i = 0; i < nmask - 1; i++) {
vector<KeyPoint> tem_keypoints_empty;
detector->detect(emptyImg, tem_keypoints_empty,rects[i]);
//string name="rects";
//imshow((name + to_string(i)).c_str(), rects[i]);
//waitKey(1);
keypoints_empty.insert(keypoints_empty.end(), tem_keypoints_empty.begin(), tem_keypoints_empty.end());
}
Mat showImg=highlight(emptyImg,mask),resultImg;
drawKeypoints(showImg, keypoints_empty, resultImg,Scalar(0,255,255));
imshow("keyImg", resultImg);
waitKey();
return 0;
}
Mat highlight(Mat srcImg, Mat mask) {
if (srcImg.size != mask.size) {
cout << "Your two images tried to highlight have different SIZE.\n";
exit(1);
}
if (mask.channels() != 1)
cvtColor(mask, mask, COLOR_BGR2GRAY);
if (mask.type() != CV_8UC1)
mask.convertTo(mask, CV_8UC1);
threshold(mask, mask, 0, 255, THRESH_BINARY_INV + THRESH_OTSU);
cvtColor(mask, mask, COLOR_GRAY2BGR);
if (srcImg.channels() != 3)
cvtColor(srcImg, srcImg, COLOR_GRAY2BGR);
if (srcImg.type() != CV_8UC3)
srcImg.convertTo(srcImg, CV_8UC3);
dilate(mask - Scalar(0, 0, 255), mask, Mat(), Point(-1, -1), 2);
return srcImg - mask;
}
I don't think any problem in my code, but the resultImg
make me confused very much..And this is my test image
As we see, there are two problem in my method.
- There are some keypoints out of the white rectange
- Some rectangle have a few keypoints even have none
Can anybody can help me out?
i think, you misunderstood something:
this will restrict it to a maximum of 10 kp. while you probably expected it to deliver at least 10.
if there's no text, or lines, or corners, there can be no keypoints found.
then, you fooled yourself with that "masking". you draw a checkerboard into your mask, but never use it for kp detection. the rects used in the detection are all white !
@berak I know that meaning. And I know the flaw in my current method. So I post such question for help to improve, because I hope those white area always have 10 keypoints.
well, not like this. imho, your whole thing is broken beyond repair. throw it away.
that sounds like a broken expectation already. look at the bottom left / right rectangles, they're simply blank. you can't get any kp there
I have used that mask(rects[i]) actually. Note here please.
@berak Since you think my solution is bad. Could you give better thinking? Help..
ah, right. apologies for getting a bit grumpy/impatient there..
@berak It can be understood.. much less I always receive your help.