我想使用OpenCV檢測與場景中其他元素明顯不同的對象,因爲它是灰色的。這很好,因爲我可以用R == G == B來運行一個測試,並且它允許獨立於亮度,但是逐個像素地執行是很慢的。使用OpenCV檢測灰色物體
有沒有更快的方法來檢測灰色的東西?也許有一種OpenCV方法可以進行R == G == B測試...... cv2.inRange
確實可以進行顏色閾值處理,這並不完全符合我的要求。
我想使用OpenCV檢測與場景中其他元素明顯不同的對象,因爲它是灰色的。這很好,因爲我可以用R == G == B來運行一個測試,並且它允許獨立於亮度,但是逐個像素地執行是很慢的。使用OpenCV檢測灰色物體
有沒有更快的方法來檢測灰色的東西?也許有一種OpenCV方法可以進行R == G == B測試...... cv2.inRange
確實可以進行顏色閾值處理,這並不完全符合我的要求。
我可以在Python找到的最快的方法是使用切片給每個信道進行比較。經過幾次測試後,此方法比兩個嵌套for循環快200倍以上。
bg = im[:,:,0] == im[:,:,1] # B == G
gr = im[:,:,1] == im[:,:,2] # G == R
slices = np.bitwise_and(bg, gr, dtype= np.uint8) * 255
這將生成一個二進制圖像,灰色物體用白色像素表示。如果不需要的二進制圖像,但僅以灰度像素由True
值指示的邏輯陣列,此方法獲得更快:
slices = np.bitwise_and(bg, gr)
省略類型轉換和乘法產生一個方法比嵌套快500倍循環。
該測試圖像上運行此操作:
給出以下結果:
正如你可以看到,灰度對象被正確檢測。
很適合給Python代碼 – remi
我很驚訝,這樣一個簡單的檢查很慢,可能你沒有有效地編碼它。
這是一段代碼,應該爲你做。它既不最佳的速度,也沒有在內存中,但相當的代碼:)
std::vector<cv::Mat> planes;
cv::split(image, planes);
cv::Mat mask = planes[0] == planes[1];
mask &= planes[1] == planes[2];
線的緣故吧的數量,這裏的東西比較這將是做到這一點,我認爲最快的方法(沒有並行化)
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <vector>
#include <sys/time.h> //gettimeofday
static
double
P_ellapsedTime(struct timeval t0, struct timeval t1)
{
//return ellapsed time in seconds
return (t1.tv_sec-t0.tv_sec)*1.0 + (t1.tv_usec-t0.tv_usec)/1000000.0;
}
int
main(int argc, char* argv[])
{
struct timeval t0, t1;
cv::Mat image = cv::imread(argv[1]);
assert(image.type() == CV_8UC3);
std::vector<cv::Mat> planes;
std::cout << "Image resolution=" << image.rows << "x" << image.cols << std::endl;
gettimeofday(&t0, NULL);
cv::split(image, planes);
cv::Mat mask = planes[0] == planes[1];
mask &= planes[1] == planes[2];
gettimeofday(&t1, NULL);
std::cout << "Time using split: " << P_ellapsedTime(t0, t1) << "s" << std::endl;
cv::Mat mask2 = cv::Mat::zeros(image.size(), CV_8U);
unsigned char *imgBuf = image.data;
unsigned char *maskBuf = mask2.data;
gettimeofday(&t0, NULL);
for (; imgBuf != image.dataend; imgBuf += 3, maskBuf++)
*maskBuf = (imgBuf[0] == imgBuf[1] && imgBuf[1] == imgBuf[2]) ? 255 : 0;
gettimeofday(&t1, NULL);
std::cout << "Time using loop: " << P_ellapsedTime(t0, t1) << "s" << std::endl;
cv::namedWindow("orig", 0);
cv::imshow("orig", image);
cv::namedWindow("mask", 0);
cv::imshow("mask", mask);
cv::namedWindow("mask2", 0);
cv::imshow("mask2", mask2);
cv::waitKey(0);
}
臺的圖像上:
Image resolution=3171x2179
Time using split: 0.06353s
Time using loop: 0.029044s
如何分割圖像I - >(A,B,C),然後檢查[(A-B)+(A-C)] == 0? (首先將圖像轉換爲簽名格式)。你會避免逐像素的事情。 –
或;拆分圖像,使用absdiff並限制圖像。 – Nallath
hmmm,如果R == G == B,則2R-G-B = 0。如何計算2R-G-B然後使用countNonZero?只是一個預感。 – GilLevi