如何去除精巧边缘图像中的长边缘?
Posted
技术标签:
【中文标题】如何去除精巧边缘图像中的长边缘?【英文标题】:How to remove long edges in a canny edge image? 【发布时间】:2016-10-19 09:23:10 【问题描述】:处理精明边缘检测后,我得到边缘图像。 但我只想保持短边(边缘来自角色)。 并且有一些长边(这里我定义为超过图片高度的一半)。示例图片如下所示:
那么如何去除超过图片一半高度的边缘?
相关问题: remove horizontal/vertical long edges
【问题讨论】:
【参考方案1】:您可以对包含边缘的minAreaRect
应用一些约束。
你可以找到一个例子here,但是由于你的边缘接触到了边框,你需要一个额外的技巧来让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;
【讨论】:
太棒了!感谢您的解决方案。你能给我一些关于如何去除我不需要的其他边缘的建议(比如右边的边缘,但它们不够长)? 稍微增加thresh_ar
,例如至 0.075 或 0.1。对字母的最大高度进行一些限制......像这样......它确实特定于您的上下文。只有边缘可以去除一些噪音,但你需要更强大的东西来去除除了你的字母之外的所有东西
非常感谢。我会试试看的!以上是关于如何去除精巧边缘图像中的长边缘?的主要内容,如果未能解决你的问题,请参考以下文章
目标 C:如何在不损失边缘质量的情况下从 JPG 图像中去除白色背景