我有一个形状像这样的透明图像。我们可以提取UIBezierPath
该图像的 吗?例如,我在UIView
课堂上可以自己画一个六边形,但我无法得到UIBezierPath
这个形状的形状。
class FreeShapeView: UIView {
override func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
context?.clear(rect)
context?.setAllowsAntialiasing(true)
context?.setShouldAntialias(true)
context?.setLineJoin(CGLineJoin.round)
let edge: CGFloat = 5.9/2
let path: UIBezierPath = UIBezierPath()
path.move(to: CGPoint(x: rect.width/2, y: edge))
path.addLine(to: CGPoint(x: rect.width - edge, y: rect.height/3))
path.addLine(to: CGPoint(x: rect.width - edge, y: rect.height/3*2))
path.addLine(to: CGPoint(x: rect.width/2, y: rect.height - edge))
path.addLine(to: CGPoint(x: edge, y: rect.height/3*2))
path.addLine(to: CGPoint(x: edge, y: rect.height/3))
path.close()
context?.addPath(path.cgPath)
}
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .clear
}
required init?(coder: NSCoder) {
super.init(coder: coder)
backgroundColor = .clear
}
}
我的 OpenCV Objective C 代码
+ (UIBezierPath *)removeTransparentAreaAndFindContours:(UIImage *)image {
// Convert UIImage to cv::Mat
cv::Mat cvImage = [self cvMatFromUIImage:image];
// Convert image to grayscale
cv::Mat grayscaleImage;
cv::cvtColor(cvImage, grayscaleImage, cv::COLOR_RGBA2GRAY);
// Apply threshold to create binary image
cv::Mat binaryImage;
cv::threshold(grayscaleImage, binaryImage, 1, 255, cv::THRESH_BINARY);
// Find contours
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(binaryImage, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
// Create a UIBezierPath from the contours
UIBezierPath *bezierPath = [UIBezierPath bezierPath];
for (size_t i = 0; i < contours.size(); i++) {
const std::vector<cv::Point> &contour = contours[i];
for (size_t j = 0; j < contour.size(); j++) {
const cv::Point &point = contour[j];
CGPoint cgPoint = CGPointMake(point.x, point.y);
if (j == 0) {
[bezierPath moveToPoint:cgPoint];
} else {
[bezierPath addLineToPoint:cgPoint];
}
}
[bezierPath closePath];
}
return bezierPath;
}
+ (cv::Mat)cvMatFromUIImage:(UIImage *)image {
CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage);
CGFloat cols = image.size.width;
CGFloat rows = image.size.height;
cv::Mat cvMat(rows, cols, CV_8UC4); // 8 bits per channel, 4 channels (RGBA)
CGContextRef contextRef = CGBitmapContextCreate(cvMat.data, cols, rows, 8, cvMat.step[0], colorSpace, kCGImageAlphaNoneSkipLast | kCGBitmapByteOrderDefault);
CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image.CGImage);
CGContextRelease(contextRef);
return cvMat;
}
我得到这样的结果。
Element 1: Type = MoveToPoint, Points = (0.0, 0.0) (6.9370081173396e-310, 0.0)
Element 2: Type = AddLineToPoint, Points = (0.0, 794.0) (6.9370081173396e-310, 0.0)
Element 3: Type = AddLineToPoint, Points = (619.0, 794.0) (6.9370081173396e-310, 0.0)
Element 4: Type = AddLineToPoint, Points = (620.0, 795.0) (6.9370081173396e-310, 0.0)
Element 5: Type = AddLineToPoint, Points = (620.0, 1270.0) (6.9370081173396e-310, 0.0)
Element 6: Type = AddLineToPoint, Points = (1998.0, 1270.0) (6.9370081173396e-310, 0.0)
Element 7: Type = AddLineToPoint, Points = (1998.0, 0.0) (6.9370081173396e-310, 0.0)
Element 8: Type = CloseSubpath, Points = (1998.0, 0.0) (6.9370081173396e-310, 0.0)
测试代码是:
path = UIBezierPath()
path.move(to: CGPoint(x: 0.0, y: 0.0))
path.addLine(to: CGPoint(x:0.0 , y:794.0 ))
path.addLine(to: CGPoint(x:619.0 , y:794.0 ))
path.addLine(to: CGPoint(x: 620.0, y: 795.0 ))
path.addLine(to: CGPoint(x:620.0 , y:1270.0 ))
path.addLine(to: CGPoint(x: 1998.0, y:1270.0 ))
path.addLine(to: CGPoint(x:1998.0 , y: 0.0))
path.close()
context?.addPath(path.cgPath)
但它是这样画的:
我究竟做错了什么 ?谢谢
您的原始图像尺寸是
5997 x 3811
.生成的坐标为您提供了一个
UIBezierPath
边界框大小为 的坐标1998.0 x 1270.0
。我不使用OpenCV
,但它似乎是基于@3x
设备比例 - 所以你得到的坐标是点而不是像素。无论如何,如果您只是尝试
1998.0 x 1270.0
在视图等中绘制路径300 x 300
,您将只能看到路径的左上角部分。如果缩放路径以适合视图,您将看到整个路径: