巧妙なエッジ検出を処理した後、エッジ画像を取得します。しかし、私は短いエッジを維持したいだけです(エッジはキャラクターから来ました)。また、いくつかの長いエッジがあります (ここでは、図の高さの半分以上を横切る長さを定義しています)。サンプル画像は次のようになります。
では、画像の高さの半分以上を横切るエッジを削除するにはどうすればよいでしょうか?
関連する質問: 水平/垂直の長辺を削除する
巧妙なエッジ検出を処理した後、エッジ画像を取得します。しかし、私は短いエッジを維持したいだけです(エッジはキャラクターから来ました)。また、いくつかの長いエッジがあります (ここでは、図の高さの半分以上を横切る長さを定義しています)。サンプル画像は次のようになります。
では、画像の高さの半分以上を横切るエッジを削除するにはどうすればよいでしょうか?
関連する質問: 水平/垂直の長辺を削除する
minAreaRect
エッジを含む に何らかの制約を適用できます。ここで例を見つけることができますが、エッジが境界線に接してfindContours
いるため、正しく機能させるには追加のトリックが必要なので、改善されたコードの下にあります。
アスペクト比に単純な制約を適用すると、次のようになります。
赤いエッジを削除した場所:
height
特定の目的に合わせて、たとえば に制約を追加できます。
ここにコード:
#include<opencv2/opencv.hpp>
using namespace cv;
int main()
{
// Load image
Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);
// Remove JPG artifacts
img = img > 200;
Mat1b result = img.clone();
// Create output image
Mat3b out;
cvtColor(img, out, COLOR_GRAY2BGR);
// Find contours
Mat1b padded;
copyMakeBorder(img, padded, 1, 1, 1, 1, BORDER_CONSTANT, Scalar(0));
vector<vector<Point>> contours;
findContours(padded, contours, RETR_LIST, CHAIN_APPROX_NONE, Point(-1, -1));
for (const auto& contour : contours)
{
// Find minimum area rectangle
RotatedRect rr = minAreaRect(contour);
// Compute aspect ratio
float aspect_ratio = min(rr.size.width, rr.size.height) / max(rr.size.width, rr.size.height);
// Define a threshold on the aspect ratio in [0, 1]
float thresh_ar = 0.05f;
// Define other constraints
bool remove = false;
if (aspect_ratio < thresh_ar) {
remove = true;
}
// if(some_other_constraint) { remove = true; }
Vec3b color;
if (remove) {
// Almost straight line
color = Vec3b(0, 0, 255); // RED
// Delete edge
for (const auto& pt : contour) {
result(pt) = uchar(0);
}
}
else {
// Curved line
color = Vec3b(0, 255, 0); // GREEN
}
// Color output image
for (const auto& pt : contour) {
out(pt) = color;
}
}
imshow("Out", out);
imshow("Result", result);
waitKey();
return 0;
}