我確實使用了findcontours()
方法從圖像中提取輪廓,但我不知道如何從一組輪廓點計算曲率。有人能幫助我嗎?非常感謝你!如何通過opencv計算提取輪廓的曲率?
7
A
回答
4
對於我曲率是:
其中t
是輪廓和x(t)
RESP內部的位置。 y(t)
返回相關的x
或分別。值爲y
。見here。
所以,根據我的曲率的定義,一個可以實現這樣說:
std::vector<float> vecCurvature(vecContourPoints.size());
cv::Point2f posOld, posOlder;
cv::Point2f f1stDerivative, f2ndDerivative;
for (size_t i = 0; i < vecContourPoints.size(); i++)
{
const cv::Point2f& pos = vecContourPoints[i];
if (i == 0){ posOld = posOlder = pos; }
f1stDerivative.x = pos.x - posOld.x;
f1stDerivative.y = pos.y - posOld.y;
f2ndDerivative.x = - pos.x + 2.0f * posOld.x - posOlder.x;
f2ndDerivative.y = - pos.y + 2.0f * posOld.y - posOlder.y;
float curvature2D = 0.0f;
if (std::abs(f2ndDerivative.x) > 10e-4 && std::abs(f2ndDerivative.y) > 10e-4)
{
curvature2D = sqrt(std::abs(
pow(f2ndDerivative.y*f1stDerivative.x - f2ndDerivative.x*f1stDerivative.y, 2.0f)/
pow(f2ndDerivative.x + f2ndDerivative.y, 3.0)));
}
vecCurvature[i] = curvature2D;
posOlder = posOld;
posOld = pos;
}
它適用於非封閉pointlists爲好。對於封閉輪廓,您可能想要更改邊界行爲(對於第一次迭代)。
UPDATE:
解釋爲衍生物:
一種用於連續1個維函數f(t)
衍生物是:
但是,我們是在一個離散的空間,並且具有兩個離散函數f_x(t)
和f_y(t)
其中最小的步驟爲t
就是其中之一。
二階導數是一階導數的導數:使用一階導數的近似值
,它產生於:
如果y有衍生物的其他近似值ou谷歌它,你會發現很多。
5
雖然Gombat的答案背後的理論是正確的,但在代碼和公式中有一些錯誤(分母t+n-x
應該是t+n-t
)。我已經提出了一些改變:
- 使用對稱衍生物獲得曲率最大值的更精確的位置
- 允許使用的步長爲導數計算(可以用來減少從嘈雜輪廓噪聲)
- 作品與閉合輪廓
修正: *返回無窮大的曲率,如果分母爲0(不爲0) *加入平方計算中的分母 *正確爲0除數檢查
std::vector<double> getCurvature(std::vector<cv::Point> const& vecContourPoints, int step)
{
std::vector<double> vecCurvature(vecContourPoints.size());
if (vecContourPoints.size() < step)
return vecCurvature;
auto frontToBack = vecContourPoints.front() - vecContourPoints.back();
std::cout << CONTENT_OF(frontToBack) << std::endl;
bool isClosed = ((int)std::max(std::abs(frontToBack.x), std::abs(frontToBack.y))) <= 1;
cv::Point2f pplus, pminus;
cv::Point2f f1stDerivative, f2ndDerivative;
for (int i = 0; i < vecContourPoints.size(); i++)
{
const cv::Point2f& pos = vecContourPoints[i];
int maxStep = step;
if (!isClosed)
{
maxStep = std::min(std::min(step, i), (int)vecContourPoints.size()-1-i);
if (maxStep == 0)
{
vecCurvature[i] = std::numeric_limits<double>::infinity();
continue;
}
}
int iminus = i-maxStep;
int iplus = i+maxStep;
pminus = vecContourPoints[iminus < 0 ? iminus + vecContourPoints.size() : iminus];
pplus = vecContourPoints[iplus > vecContourPoints.size() ? iplus - vecContourPoints.size() : iplus];
f1stDerivative.x = (pplus.x - pminus.x)/(iplus-iminus);
f1stDerivative.y = (pplus.y - pminus.y)/(iplus-iminus);
f2ndDerivative.x = (pplus.x - 2*pos.x + pminus.x)/((iplus-iminus)/2*(iplus-iminus)/2);
f2ndDerivative.y = (pplus.y - 2*pos.y + pminus.y)/((iplus-iminus)/2*(iplus-iminus)/2);
double curvature2D;
double divisor = f1stDerivative.x*f1stDerivative.x + f1stDerivative.y*f1stDerivative.y;
if (std::abs(divisor) > 10e-8)
{
curvature2D = std::abs(f2ndDerivative.y*f1stDerivative.x - f2ndDerivative.x*f1stDerivative.y)/
pow(divisor, 3.0/2.0) ;
}
else
{
curvature2D = std::numeric_limits<double>::infinity();
}
vecCurvature[i] = curvature2D;
}
return vecCurvature;
}
相關問題
- 1. 如何通過opencv判斷輪廓是線還是曲線?
- 2. 用matplotlib創建的輪廓使用opencv計算輪廓區域
- 3. 在opencv中計算Python中的輪廓
- 4. OpenCV的(C):計算時刻從輪廓
- 5. 如何通過OpenCV流域獲取對象之間的輪廓?
- 6. 提取內部輪廓(洞)的OpenCV
- 7. OpenCV C++:通過輪廓區域對輪廓線進行排序
- 8. 從輪廓提取矩形OpenCV
- 9. 如何計算opencv中的粗糙度輪廓?
- 10. 如何計算輪廓內的非零像素opencv
- 11. 我如何計算OpenCV中的平均輪廓
- 12. 如何計算手指的數量? (openCV +輪廓檢測)
- 13. 輪廓提取
- 14. 提取輪廓
- 15. 找到輪廓後Opencv圖像扭曲
- 16. 在OpenCV中關閉輪廓曲線
- 17. 如何從輪廓提取簡單的幾何形式在opencv
- 18. (Opencv)獲取輪廓在IplImage
- 19. 如何計算輪廓的直方圖?
- 20. OpenCV輪廓?
- 21. Opencv輪廓
- 22. 搜索輪廓內的輪廓/ OpenCV C++
- 23. 從輪廓中提取最外輪廓
- 24. 我如何平滑OpenCV中的曲線(輪廓)?
- 25. OpenCV-如何統一不同的輪廓,一個封閉輪廓
- 26. 如何在Python OpenCV中去除輪廓內的輪廓?
- 27. 如何通過亮度過濾輪廓
- 28. OpenCV輪廓時刻?
- 29. Opencv輪廓錯誤
- 30. (opencv)合併輪廓
如果您向我們提供您已經嘗試過的事項清單並提供更具體的問題,這將有極大的幫助。 – YePhIcK